diff --git a/.github/dependabot.yml b/.github/dependabot.yml deleted file mode 100644 index 88241c04fd1f..000000000000 --- a/.github/dependabot.yml +++ /dev/null @@ -1,15 +0,0 @@ -# To get started with Dependabot version updates, you'll need to specify which -# package ecosystems to update and where the package manifests are located. -# Please see the documentation for all configuration options: -# https://help.github.com/github/administering-a-repository/configuration-options-for-dependency-updates - -version: 2 -updates: - - package-ecosystem: "gomod" # See documentation for possible values - directory: "/" # Location of package manifests - schedule: - interval: "monthly" - - package-ecosystem: "github-actions" - directory: "/" - schedule: - interval: "monthly" diff --git a/.github/renovate.json b/.github/renovate.json new file mode 100644 index 000000000000..319817ef7ced --- /dev/null +++ b/.github/renovate.json @@ -0,0 +1,8 @@ +{ + "$schema": "https://docs.renovatebot.com/renovate-schema.json", + "extends": [ + "config:base" + ], + "prConcurrentLimit": 3, + "prHourlyLimit": 2 +} diff --git a/Dockerfile b/Dockerfile index 2f92629480b3..89d60229cbce 100644 --- a/Dockerfile +++ b/Dockerfile @@ -8,9 +8,9 @@ RUN --mount=type=cache,target=/go/pkg/mod \ --mount=type=cache,target=/root/.cache/go-build \ GOOS=${TARGETOS} GOARCH=${TARGETARCH} go build -o trufflehog . -FROM alpine:3.15 -RUN apk add --no-cache bash git openssh-client ca-certificates \ - && update-ca-certificates +FROM alpine:3.18 +RUN apk add --no-cache bash git openssh-client ca-certificates rpm2cpio \ + && rm -rf /var/cache/apk/* && update-ca-certificates COPY --from=builder /build/trufflehog /usr/bin/trufflehog COPY entrypoint.sh /etc/entrypoint.sh RUN chmod +x /etc/entrypoint.sh diff --git a/Dockerfile.goreleaser b/Dockerfile.goreleaser index ec199ee4a3d9..db663c467885 100644 --- a/Dockerfile.goreleaser +++ b/Dockerfile.goreleaser @@ -1,8 +1,7 @@ -FROM alpine:3.15 +FROM alpine:3.18 -RUN apk add --no-cache bash git openssh-client ca-certificates \ - && rm -rf /var/cache/apk/* && \ - update-ca-certificates +RUN apk add --no-cache bash git openssh-client ca-certificates rpm2cpio \ + && rm -rf /var/cache/apk/* && update-ca-certificates WORKDIR /usr/bin/ COPY trufflehog . COPY entrypoint.sh /etc/entrypoint.sh diff --git a/Makefile b/Makefile index 261c884fe07d..1cff4115b939 100644 --- a/Makefile +++ b/Makefile @@ -52,10 +52,10 @@ run-debug: CGO_ENABLED=0 go run . git file://. --json --debug protos: - docker run -u "$(shell id -u)" -v "$(shell dirname $(realpath $(firstword $(MAKEFILE_LIST))))":/pwd "${PROTOS_IMAGE}" bash -c "cd /pwd; /pwd/scripts/gen_proto.sh" + docker run --rm -u "$(shell id -u)" -v "$(shell dirname $(realpath $(firstword $(MAKEFILE_LIST))))":/pwd "${PROTOS_IMAGE}" bash -c "cd /pwd; /pwd/scripts/gen_proto.sh" protos-windows: - docker run -v "$(shell cygpath -w $(shell pwd))":/pwd "${PROTOS_IMAGE}" bash -c "cd /pwd; ./scripts/gen_proto.sh" + docker run --rm -v "$(shell cygpath -w $(shell pwd))":/pwd "${PROTOS_IMAGE}" bash -c "cd /pwd; ./scripts/gen_proto.sh" release-protos-image: docker buildx build --push --platform=linux/amd64,linux/arm64 \ diff --git a/README.md b/README.md index 5c78cfc149cd..8785549f0cbb 100644 --- a/README.md +++ b/README.md @@ -164,7 +164,7 @@ trufflehog docker --image trufflesecurity/secrets --only-verified + All I see is `🐷🔑🐷 TruffleHog. Unearth your secrets. 🐷🔑🐷` and the program exits, what gives? + That means no secrets were detected -+ Why is the scan is taking a long time when I scan a GitHub org ++ Why is the scan taking a long time when I scan a GitHub org + Unauthenticated GitHub scans have rate limits. To improve your rate limits, include the `--token` flag with a personal access token + It says a private key was verified, what does that mean? + Check out our Driftwood blog post to learn how to do this, in short we've confirmed the key can be used live for SSH or SSL [Blog post](https://trufflesecurity.com/blog/driftwood-know-if-private-keys-are-sensitive/) @@ -219,7 +219,7 @@ Flags: --concurrency=10 Number of concurrent workers. --no-verification Don't verify the results. --only-verified Only output verified results. - --filter-unverified Only output first unverified result per chunk per detector if there are more than one results. + --filter-unverified Only output first unverified result per chunk per detector if there is more than one result. --config=CONFIG Path to configuration file. --print-avg-detector-time Print the average time spent on each detector. --no-update Don't check for updates. diff --git a/go.mod b/go.mod index a09acc9b5646..233ab05ef327 100644 --- a/go.mod +++ b/go.mod @@ -2,21 +2,17 @@ module github.com/trufflesecurity/trufflehog/v3 go 1.21 -replace github.com/jpillora/overseer => github.com/trufflesecurity/overseer v1.1.7-custom5 - -// go wants to pull in the latest but after v10.2.5 has a breaking API change -replace github.com/couchbase/gocbcore/v10 => github.com/couchbase/gocbcore/v10 v10.2.4 +replace github.com/jpillora/overseer => github.com/trufflesecurity/overseer v1.2.7 require ( - cloud.google.com/go/secretmanager v1.11.1 + cloud.google.com/go/secretmanager v1.11.2 cloud.google.com/go/storage v1.33.0 - github.com/Azure/go-autorest/autorest/azure/auth v0.5.11 + github.com/Azure/go-autorest/autorest/azure/auth v0.5.12 github.com/AzureAD/microsoft-authentication-library-for-go v1.2.0 github.com/BobuSumisu/aho-corasick v1.0.3 github.com/TheZeroSlave/zapsentry v1.17.0 github.com/aws/aws-sdk-go v1.45.19 - github.com/aymanbagabas/go-osc52 v1.2.1 - github.com/bill-rich/disk-buffer-reader v0.1.7 + github.com/aymanbagabas/go-osc52 v1.2.2 github.com/bill-rich/go-syslog v0.0.0-20220413021637-49edb52a574c github.com/bitfinexcom/bitfinex-api-go v0.0.0-20210608095005-9e0b26f200fb github.com/bradleyfalzon/ghinstallation/v2 v2.7.0 @@ -24,14 +20,14 @@ require ( github.com/charmbracelet/bubbletea v0.24.2 github.com/charmbracelet/glamour v0.6.0 github.com/charmbracelet/lipgloss v0.7.1 - github.com/couchbase/gocb/v2 v2.6.3 + github.com/couchbase/gocb/v2 v2.6.5 github.com/crewjam/rfc5424 v0.1.0 github.com/denisenkom/go-mssqldb v0.12.3 github.com/envoyproxy/protoc-gen-validate v1.0.2 github.com/fatih/color v1.15.0 github.com/felixge/fgprof v0.9.3 github.com/getsentry/sentry-go v0.24.1 - github.com/go-errors/errors v1.4.2 + github.com/go-errors/errors v1.5.1 github.com/go-git/go-git/v5 v5.8.1 github.com/go-ldap/ldap/v3 v3.4.6 github.com/go-logr/logr v1.2.4 @@ -40,22 +36,24 @@ require ( github.com/go-sql-driver/mysql v1.7.1 github.com/gobwas/glob v0.2.3 github.com/golang-jwt/jwt v3.2.2+incompatible - github.com/google/go-cmp v0.5.9 + github.com/google/go-cmp v0.6.0 github.com/google/go-containerregistry v0.15.2 github.com/google/go-github/v42 v42.0.0 + github.com/google/go-github/v56 v56.0.0 github.com/googleapis/gax-go/v2 v2.12.0 github.com/h2non/filetype v1.1.3 github.com/hashicorp/go-retryablehttp v0.7.4 github.com/hashicorp/golang-lru v0.5.1 + github.com/hashicorp/golang-lru/v2 v2.0.7 github.com/jlaffaye/ftp v0.2.0 github.com/joho/godotenv v1.5.1 github.com/jpillora/overseer v1.1.6 github.com/kylelemons/godebug v1.1.0 - github.com/launchdarkly/go-server-sdk/v6 v6.1.0 + github.com/launchdarkly/go-server-sdk/v6 v6.1.1 github.com/lib/pq v1.10.9 - github.com/lrstanley/bubblezone v0.0.0-20221222153816-e95291e2243e + github.com/lrstanley/bubblezone v0.0.0-20230911164824-e3824f1adde9 github.com/marusama/semaphore/v2 v2.5.0 - github.com/mattn/go-isatty v0.0.19 + github.com/mattn/go-isatty v0.0.20 github.com/mattn/go-sqlite3 v1.14.17 github.com/mholt/archiver/v4 v4.0.0-alpha.8 github.com/muesli/reflow v0.3.0 @@ -65,17 +63,18 @@ require ( github.com/prometheus/client_golang v1.16.0 github.com/rabbitmq/amqp091-go v1.8.1 github.com/sergi/go-diff v1.3.1 - github.com/snowflakedb/gosnowflake v1.6.23 + github.com/snowflakedb/gosnowflake v1.6.25 github.com/stretchr/testify v1.8.4 github.com/tailscale/depaware v0.0.0-20210622194025-720c4b409502 + github.com/trufflesecurity/disk-buffer-reader v0.1.9 github.com/xanzy/go-gitlab v0.92.3 go.mongodb.org/mongo-driver v1.12.1 go.uber.org/mock v0.2.0 go.uber.org/zap v1.24.0 golang.org/x/crypto v0.14.0 - golang.org/x/exp v0.0.0-20230206171751-46f607a40771 - golang.org/x/oauth2 v0.12.0 - golang.org/x/sync v0.3.0 + golang.org/x/exp v0.0.0-20231006140011-7918f672742d + golang.org/x/oauth2 v0.13.0 + golang.org/x/sync v0.4.0 golang.org/x/text v0.13.0 google.golang.org/api v0.132.0 google.golang.org/protobuf v1.31.0 @@ -140,7 +139,7 @@ require ( github.com/connesc/cipherio v0.2.1 // indirect github.com/containerd/console v1.0.4-0.20230313162750-1ae8d489ac81 // indirect github.com/containerd/stargz-snapshotter/estargz v0.14.3 // indirect - github.com/couchbase/gocbcore/v10 v10.2.4 // indirect + github.com/couchbase/gocbcore/v10 v10.2.9 // indirect github.com/danieljoos/wincred v1.1.2 // indirect github.com/davecgh/go-spew v1.1.1 // indirect github.com/dimchansky/utfbom v1.1.1 // indirect @@ -193,7 +192,7 @@ require ( github.com/launchdarkly/eventsource v1.6.2 // indirect github.com/launchdarkly/go-jsonstream/v3 v3.0.0 // indirect github.com/launchdarkly/go-sdk-common/v3 v3.0.1 // indirect - github.com/launchdarkly/go-sdk-events/v2 v2.0.1 // indirect + github.com/launchdarkly/go-sdk-events/v2 v2.0.2 // indirect github.com/launchdarkly/go-semver v1.0.2 // indirect github.com/launchdarkly/go-server-sdk-evaluation/v2 v2.0.2 // indirect github.com/lucasb-eyer/go-colorful v1.2.0 // indirect @@ -246,12 +245,12 @@ require ( go.uber.org/atomic v1.7.0 // indirect go.uber.org/multierr v1.6.0 // indirect go4.org v0.0.0-20200411211856-f5505b9728dd // indirect - golang.org/x/mod v0.12.0 // indirect + golang.org/x/mod v0.13.0 // indirect golang.org/x/net v0.17.0 // indirect golang.org/x/sys v0.13.0 // indirect golang.org/x/term v0.13.0 // indirect golang.org/x/time v0.3.0 // indirect - golang.org/x/tools v0.12.0 // indirect + golang.org/x/tools v0.14.0 // indirect golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 // indirect google.golang.org/appengine v1.6.7 // indirect google.golang.org/genproto v0.0.0-20230706204954-ccb25ca9f130 // indirect diff --git a/go.sum b/go.sum index 704cc19c573b..e1115db8aeac 100644 --- a/go.sum +++ b/go.sum @@ -22,6 +22,8 @@ cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2k cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw= cloud.google.com/go/secretmanager v1.11.1 h1:cLTCwAjFh9fKvU6F13Y4L9vPcx9yiWPyWXE4+zkuEQs= cloud.google.com/go/secretmanager v1.11.1/go.mod h1:znq9JlXgTNdBeQk9TBW/FnR/W4uChEKGeqQWAJ8SXFw= +cloud.google.com/go/secretmanager v1.11.2 h1:52Z78hH8NBWIqbvIG0wi0EoTaAmSx99KIOAmDXIlX0M= +cloud.google.com/go/secretmanager v1.11.2/go.mod h1:MQm4t3deoSub7+WNwiC4/tRYgDBHJgJPvswqQVB1Vss= cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw= cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos= cloud.google.com/go/storage v1.33.0 h1:PVrDOkIC8qQVa1P3SXGpQvfuJhN2LHOoyZvWs8D2X5M= @@ -52,6 +54,8 @@ github.com/Azure/go-autorest/autorest/adal v0.9.18 h1:kLnPsRjzZZUF3K5REu/Kc+qMQr github.com/Azure/go-autorest/autorest/adal v0.9.18/go.mod h1:XVVeme+LZwABT8K5Lc3hA4nAe8LDBVle26gTrguhhPQ= github.com/Azure/go-autorest/autorest/azure/auth v0.5.11 h1:P6bYXFoao05z5uhOQzbC3Qd8JqF3jUoocoTeIxkp2cA= github.com/Azure/go-autorest/autorest/azure/auth v0.5.11/go.mod h1:84w/uV8E37feW2NCJ08uT9VBfjfUHpgLVnG2InYD6cg= +github.com/Azure/go-autorest/autorest/azure/auth v0.5.12 h1:wkAZRgT/pn8HhFyzfe9UnqOjJYqlembgCTi72Bm/xKk= +github.com/Azure/go-autorest/autorest/azure/auth v0.5.12/go.mod h1:84w/uV8E37feW2NCJ08uT9VBfjfUHpgLVnG2InYD6cg= github.com/Azure/go-autorest/autorest/azure/cli v0.4.5 h1:0W/yGmFdTIT77fvdlGZ0LMISoLHFJ7Tx4U0yeB+uFs4= github.com/Azure/go-autorest/autorest/azure/cli v0.4.5/go.mod h1:ADQAXrkgm7acgWVUNamOgh8YNrv4p27l3Wc55oVfpzg= github.com/Azure/go-autorest/autorest/date v0.3.0 h1:7gUk1U5M/CQbp9WoqinNzJar+8KY+LPI6wiWrP/myHw= @@ -147,6 +151,8 @@ github.com/aws/smithy-go v1.13.5/go.mod h1:Tg+OJXh4MB2R/uN61Ko2f6hTZwB/ZYGOtib8J github.com/aymanbagabas/go-osc52 v1.0.3/go.mod h1:zT8H+Rk4VSabYN90pWyugflM3ZhpTZNC7cASDfUCdT4= github.com/aymanbagabas/go-osc52 v1.2.1 h1:q2sWUyDcozPLcLabEMd+a+7Ea2DitxZVN9hTxab9L4E= github.com/aymanbagabas/go-osc52 v1.2.1/go.mod h1:zT8H+Rk4VSabYN90pWyugflM3ZhpTZNC7cASDfUCdT4= +github.com/aymanbagabas/go-osc52 v1.2.2 h1:NT7wkhEhPTcKnBCdPi9djmyy9L3JOL4+3SsfJyqptCo= +github.com/aymanbagabas/go-osc52 v1.2.2/go.mod h1:zT8H+Rk4VSabYN90pWyugflM3ZhpTZNC7cASDfUCdT4= github.com/aymanbagabas/go-osc52/v2 v2.0.1 h1:HwpRHbFMcZLEVr42D4p7XBqjyuxQH5SMiErDT4WkJ2k= github.com/aymanbagabas/go-osc52/v2 v2.0.1/go.mod h1:uYgXzlJ7ZpABp8OJ+exZzJJhRNQ2ASbcXHWsFqH8hp8= github.com/aymerick/douceur v0.2.0 h1:Mv+mAeH1Q+n9Fr+oyamOlAkUNPWPlA8PPGR0QAaYuPk= @@ -155,8 +161,6 @@ github.com/benbjohnson/clock v1.1.0 h1:Q92kusRqC1XV2MjkWETPvjJVqKetz1OzxZB7mHJLj github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= -github.com/bill-rich/disk-buffer-reader v0.1.7 h1:oPgDjsbeqErOrFJeWID/51LhIOGjU3cqN1Tj3V6RiwE= -github.com/bill-rich/disk-buffer-reader v0.1.7/go.mod h1:VVzzsK1Ac2AnpOfp/5r9JlIFaFkZ9uSf7zisZayCt0Y= github.com/bill-rich/go-syslog v0.0.0-20220413021637-49edb52a574c h1:tSME5FDS02qQll3JYodI6RZR/g4EKOHApGv1wMZT+Z0= github.com/bill-rich/go-syslog v0.0.0-20220413021637-49edb52a574c/go.mod h1:+sCc6hztur+oZCLOsNk6wCCy+GLrnSNHSRmTnnL+8iQ= github.com/bitfinexcom/bitfinex-api-go v0.0.0-20210608095005-9e0b26f200fb h1:9v7Bzlg+1EBYi2IYcUmOwHReBEfqBbYIj3ZCi9cIe1Q= @@ -204,8 +208,12 @@ github.com/containerd/stargz-snapshotter/estargz v0.14.3 h1:OqlDCK3ZVUO6C3B/5FSk github.com/containerd/stargz-snapshotter/estargz v0.14.3/go.mod h1:KY//uOCIkSuNAHhJogcZtrNHdKrA99/FCCRjE3HD36o= github.com/couchbase/gocb/v2 v2.6.3 h1:5RsMo+RRfK0mVxHLAfpBz3/tHlgXZb1WBNItLk9Ab+c= github.com/couchbase/gocb/v2 v2.6.3/go.mod h1:yF5F6BHTZ/ZowhEuZbySbXrlI4rHd1TIhm5azOaMbJU= +github.com/couchbase/gocb/v2 v2.6.5 h1:xaZu29o8UJEV1ZQ3n2s9jcRCUHz/JsQ6+y6JBnVsy5A= +github.com/couchbase/gocb/v2 v2.6.5/go.mod h1:0vFM09y+VPhnXeNrIb8tS0wKHGpJvjJBrJnriWEiwGs= github.com/couchbase/gocbcore/v10 v10.2.4 h1:TDTQ1mSBUw9eajuV71ZDJcLRbmfGcsvZV9SMeUDAVGc= github.com/couchbase/gocbcore/v10 v10.2.4/go.mod h1:lYQIIk+tzoMcwtwU5GzPbDdqEkwkH3isI2rkSpfL0oM= +github.com/couchbase/gocbcore/v10 v10.2.9 h1:zph/+ceu3JtZEDKhJMTRc6lGrahq+mnlQY/1dSepJuE= +github.com/couchbase/gocbcore/v10 v10.2.9/go.mod h1:lYQIIk+tzoMcwtwU5GzPbDdqEkwkH3isI2rkSpfL0oM= github.com/couchbaselabs/gocaves/client v0.0.0-20230307083111-cc3960c624b1/go.mod h1:AVekAZwIY2stsJOMWLAS/0uA/+qdp7pjO8EHnl61QkY= github.com/couchbaselabs/gocaves/client v0.0.0-20230404095311-05e3ba4f0259 h1:2TXy68EGEzIMHOx9UvczR5ApVecwCfQZ0LjkmwMI6g4= github.com/couchbaselabs/gocaves/client v0.0.0-20230404095311-05e3ba4f0259/go.mod h1:AVekAZwIY2stsJOMWLAS/0uA/+qdp7pjO8EHnl61QkY= @@ -271,6 +279,8 @@ github.com/go-asn1-ber/asn1-ber v1.5.5 h1:MNHlNMBDgEKD4TcKr36vQN68BA00aDfjIt3/bD github.com/go-asn1-ber/asn1-ber v1.5.5/go.mod h1:hEBeB/ic+5LoWskz+yKT7vGhhPYkProFKoKdwZRWMe0= github.com/go-errors/errors v1.4.2 h1:J6MZopCL4uSllY1OfXM374weqZFFItUbrImctkmUxIA= github.com/go-errors/errors v1.4.2/go.mod h1:sIVyrIiJhuEF+Pj9Ebtd6P/rEYROXFi3BopGUQ5a5Og= +github.com/go-errors/errors v1.5.1 h1:ZwEMSLRCapFLflTpT7NKaAc7ukJ8ZPEjzlxt8rPN8bk= +github.com/go-errors/errors v1.5.1/go.mod h1:sIVyrIiJhuEF+Pj9Ebtd6P/rEYROXFi3BopGUQ5a5Og= github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 h1:+zs/tPmkDkHx3U66DAb0lQFJrpS6731Oaa12ikc+DiI= github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376/go.mod h1:an3vInlBmSxCcxctByoQdvwPiA7DTK7jaaFDBTtu0ic= github.com/go-git/go-billy/v5 v5.4.1 h1:Uwp5tDRkPr+l/TnbHOQzp+tmJfLceOlbVucgpTz8ix4= @@ -363,12 +373,15 @@ github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= +github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-containerregistry v0.15.2 h1:MMkSh+tjSdnmJZO7ljvEqV1DjfekB6VUEAZgy3a+TQE= github.com/google/go-containerregistry v0.15.2/go.mod h1:wWK+LnOv4jXMM23IT/F1wdYftGWGr47Is8CG+pmHK1Q= github.com/google/go-github/v42 v42.0.0 h1:YNT0FwjPrEysRkLIiKuEfSvBPCGKphW5aS5PxwaoLec= github.com/google/go-github/v42 v42.0.0/go.mod h1:jgg/jvyI0YlDOM1/ps6XYh04HNQ3vKf0CVko62/EhRg= github.com/google/go-github/v55 v55.0.0 h1:4pp/1tNMB9X/LuAhs5i0KQAE40NmiR/y6prLNb9x9cg= github.com/google/go-github/v55 v55.0.0/go.mod h1:JLahOTA1DnXzhxEymmFF5PP2tSS9JVNj68mSZNDwskA= +github.com/google/go-github/v56 v56.0.0/go.mod h1:D8cdcX98YWJvi7TLo7zM4/h8ZTx6u6fwGEkCdisopo0= github.com/google/go-querystring v1.1.0 h1:AnCroh3fv4ZBgVIf1Iwtovgjaw/GiKJo8M8yD/fhyJ8= github.com/google/go-querystring v1.1.0/go.mod h1:Kcdr2DB4koayq7X8pmAG4sNG59So17icRSOU623lUBU= github.com/google/martian v2.1.0+incompatible h1:/CP5g8u/VJHijgedC/Legn3BAbAaWPgecwXBIDzw5no= @@ -418,6 +431,8 @@ github.com/hashicorp/go-retryablehttp v0.7.4/go.mod h1:Jy/gPYAdjqffZ/yFGCFV2doI5 github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/golang-lru v0.5.1 h1:0hERBMJE1eitiLkihrMvRVBYAkpHzc/J3QdDN+dAcgU= github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= +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/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/ianlancetaylor/demangle v0.0.0-20210905161508-09a460cdf81d/go.mod h1:aYm2/VgdVmcIU8iMfdMvDMsRAQjcfZSKFby6HOFvi/w= @@ -473,12 +488,16 @@ github.com/launchdarkly/go-sdk-common/v3 v3.0.1 h1:rVdLusAIViduNvyjNKy06RA+SPwk0 github.com/launchdarkly/go-sdk-common/v3 v3.0.1/go.mod h1:H/zISoCNhviHTTqqBjIKQy2YgSHT8ioL1FtgBKpiEGg= github.com/launchdarkly/go-sdk-events/v2 v2.0.1 h1:vnUN2Y7og/5wtOCcCZW7wYpmZcS++GAyclasc7gaTIY= github.com/launchdarkly/go-sdk-events/v2 v2.0.1/go.mod h1:Msqbl6brgFO83RUxmLaJAUx2sYG+WKULcy+Vf3+tKww= +github.com/launchdarkly/go-sdk-events/v2 v2.0.2 h1:Ngp050AGYUyN3YRxX7zfu110NETHEPEOVys1ey2Hyvw= +github.com/launchdarkly/go-sdk-events/v2 v2.0.2/go.mod h1:Msqbl6brgFO83RUxmLaJAUx2sYG+WKULcy+Vf3+tKww= github.com/launchdarkly/go-semver v1.0.2 h1:sYVRnuKyvxlmQCnCUyDkAhtmzSFRoX6rG2Xa21Mhg+w= github.com/launchdarkly/go-semver v1.0.2/go.mod h1:xFmMwXba5Mb+3h72Z+VeSs9ahCvKo2QFUTHRNHVqR28= github.com/launchdarkly/go-server-sdk-evaluation/v2 v2.0.2 h1:PAM0GvE0nIUBeOkjdiymIEKI+8FFLJ+fEsWTupW1yGU= github.com/launchdarkly/go-server-sdk-evaluation/v2 v2.0.2/go.mod h1:Mztipcz+7ZMatXVun3k/IfPa8IOgUnAqiZawtFh2MRg= github.com/launchdarkly/go-server-sdk/v6 v6.1.0 h1:pp/VBIon5JNbtSw7ih7I5MXN9mXHfo6T5xikKVy52dI= github.com/launchdarkly/go-server-sdk/v6 v6.1.0/go.mod h1:3TfS6vNsNksPT4LGeGuGKtT3zTjTbbOsCUK3nrj1neA= +github.com/launchdarkly/go-server-sdk/v6 v6.1.1 h1:L57BC9Fy4IJG0zRZoYBkoxko6QTAC2OF8QzTVUqn2p8= +github.com/launchdarkly/go-server-sdk/v6 v6.1.1/go.mod h1:67QqqyeRNyXx7S/fZiSZesRvaePCyxhzsnY+4fhK55U= github.com/launchdarkly/go-test-helpers/v2 v2.2.0 h1:L3kGILP/6ewikhzhdNkHy1b5y4zs50LueWenVF0sBbs= github.com/launchdarkly/go-test-helpers/v2 v2.2.0/go.mod h1:L7+th5govYp5oKU9iN7To5PgznBuIjBPn+ejqKR0avw= github.com/launchdarkly/go-test-helpers/v3 v3.0.2 h1:rh0085g1rVJM5qIukdaQ8z1XTWZztbJ49vRZuveqiuU= @@ -487,6 +506,8 @@ github.com/lib/pq v1.10.9 h1:YXG7RB+JIjhP29X+OtkiDnYaXQwpS4JEWq7dtCCRUEw= github.com/lib/pq v1.10.9/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= github.com/lrstanley/bubblezone v0.0.0-20221222153816-e95291e2243e h1:XoxHx8K6ZKoMtjzWOMDuM69LCdjDDsTOtTfWGrT/fns= github.com/lrstanley/bubblezone v0.0.0-20221222153816-e95291e2243e/go.mod h1:v5lEwWaguF1o2MW/ucO0ZIA/IZymdBYJJ+2cMRLE7LU= +github.com/lrstanley/bubblezone v0.0.0-20230911164824-e3824f1adde9 h1:+7bxeCzFs4bfFPAnIZrjNmRt/MCffIy7aw2mPc9mxkU= +github.com/lrstanley/bubblezone v0.0.0-20230911164824-e3824f1adde9/go.mod h1:v5lEwWaguF1o2MW/ucO0ZIA/IZymdBYJJ+2cMRLE7LU= github.com/lucasb-eyer/go-colorful v1.2.0 h1:1nnpGOrhyZZuNyfu1QjKiUICQ74+3FNCN69Aj6K7nkY= github.com/lucasb-eyer/go-colorful v1.2.0/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0= github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0= @@ -500,6 +521,8 @@ github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovk github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= github.com/mattn/go-isatty v0.0.19 h1:JITubQf0MOLdlGRuRq+jtsDlekdYPia9ZFsB8h/APPA= github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= +github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= +github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= github.com/mattn/go-localereader v0.0.1 h1:ygSAOl7ZXTx4RdPYinUpg6W99U8jWvWi9Ye2JC/oIi4= github.com/mattn/go-localereader v0.0.1/go.mod h1:8fBrzywKY7BI3czFoHkuzRoWE9C+EiG4R1k4Cjx5p88= github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= @@ -616,6 +639,8 @@ github.com/smartystreets/gunit v1.1.3 h1:32x+htJCu3aMswhPw3teoJ+PnWPONqdNgaGs6Qt github.com/smartystreets/gunit v1.1.3/go.mod h1:EH5qMBab2UclzXUcpR8b93eHsIlp9u+pDQIRp5DZNzQ= github.com/snowflakedb/gosnowflake v1.6.23 h1:uO+zMTXJcSHzOm6ks5To8ergNjt5Dy6cr5QtStpRFT8= github.com/snowflakedb/gosnowflake v1.6.23/go.mod h1:KfO4F7bk+aXPUIvBqYxvPhxLlu2/w4TtSC8Rw/yr5Mg= +github.com/snowflakedb/gosnowflake v1.6.25 h1:o5zUmxTOo0Eo9AdkEj8blCeiMuILrQJ+rjUMAeZhcRE= +github.com/snowflakedb/gosnowflake v1.6.25/go.mod h1:KfO4F7bk+aXPUIvBqYxvPhxLlu2/w4TtSC8Rw/yr5Mg= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= github.com/stretchr/objx v0.5.0 h1:1zr/of2m5FGMsad5YfcqgdqdWrIhu+EBEJRhR1U7z/c= @@ -637,8 +662,12 @@ github.com/tailscale/depaware v0.0.0-20210622194025-720c4b409502 h1:34icjjmqJ2HP github.com/tailscale/depaware v0.0.0-20210622194025-720c4b409502/go.mod h1:p9lPsd+cx33L3H9nNoecRRxPssFKUwwI50I3pZ0yT+8= github.com/therootcompany/xz v1.0.1 h1:CmOtsn1CbtmyYiusbfmhmkpAAETj0wBIH6kCYaX+xzw= github.com/therootcompany/xz v1.0.1/go.mod h1:3K3UH1yCKgBneZYhuQUvJ9HPD19UEXEI0BWbMn8qNMY= +github.com/trufflesecurity/disk-buffer-reader v0.1.9 h1:1dji/Cx5aPL5DlsqI1B86xFMo6OfbBEhkQhXxgbX9WA= +github.com/trufflesecurity/disk-buffer-reader v0.1.9/go.mod h1:uYwTCdxzV0o+qaeBMxflOsq4eu2WjrE46qGR2e80O9Y= github.com/trufflesecurity/overseer v1.1.7-custom5 h1:xu+Fg6fkSRifUPzUCl7N8HmobJ6WGOkIApGnM7mJS6w= github.com/trufflesecurity/overseer v1.1.7-custom5/go.mod h1:nT9w37AiO1Nop2VhVhNfzAFaPjthvxgpDV3XKsxYkcI= +github.com/trufflesecurity/overseer v1.2.7 h1:DEiu2wrL/0f+XqshIT9C4/0nj7SHZvLmFeE4jELh4Oo= +github.com/trufflesecurity/overseer v1.2.7/go.mod h1:nT9w37AiO1Nop2VhVhNfzAFaPjthvxgpDV3XKsxYkcI= github.com/ulikunitz/xz v0.5.6/go.mod h1:2bypXElzHzzJZwzH67Y6wb67pO62Rzfn7BSiF4ABRW8= github.com/ulikunitz/xz v0.5.10 h1:t92gobL9l3HE202wg3rlk19F6X+JOxl9BBrCCMYEYd8= github.com/ulikunitz/xz v0.5.10/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14= @@ -720,6 +749,8 @@ golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u0 golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM= golang.org/x/exp v0.0.0-20230206171751-46f607a40771 h1:xP7rWLUr1e1n2xkK5YB4LI0hPEy3LJC6Wk+D4pGlOJg= golang.org/x/exp v0.0.0-20230206171751-46f607a40771/go.mod h1:CxIveKay+FTh1D0yPZemJVgC/95VzuuOLq5Qi4xnoYc= +golang.org/x/exp v0.0.0-20231006140011-7918f672742d h1:jtJma62tbqLibJ5sFQz8bKtEM8rJBtfilJ2qTU199MI= +golang.org/x/exp v0.0.0-20231006140011-7918f672742d/go.mod h1:ldy0pHrwJyGW56pPQzzkH36rKxoZW1tw7ZJpeKx+hdo= golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= @@ -744,6 +775,8 @@ golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91 golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/mod v0.12.0 h1:rmsUpXtvNzj340zd98LZ4KntptpfRHwpFOHG188oHXc= golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= +golang.org/x/mod v0.13.0 h1:I/DsJXRlw/8l/0c24sM9yb0T4z9liZTduXvdAWYiysY= +golang.org/x/mod v0.13.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -783,6 +816,8 @@ golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4Iltr golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.12.0 h1:smVPGxink+n1ZI5pkQa8y6fZT0RW0MgCO5bFpepy4B4= golang.org/x/oauth2 v0.12.0/go.mod h1:A74bZ3aGXgCY0qaIC9Ahg6Lglin4AMAco8cIv9baba4= +golang.org/x/oauth2 v0.13.0 h1:jDDenyj+WgFtmV3zYVoi8aE2BwtXFLWOA67ZfNWftiY= +golang.org/x/oauth2 v0.13.0/go.mod h1:/JMhi4ZRXAf4HG9LiNmxvk+45+96RUlVThiH8FzNBn0= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -795,6 +830,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 h1:ftCYgMx6zT/asHUrPw8BLLscYtGznsLAnjq5RH9P66E= golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y= +golang.org/x/sync v0.4.0 h1:zxkM55ReGkDlKSM+Fu41A+zmbZuaPVbGMzvvdUPznYQ= +golang.org/x/sync v0.4.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -905,6 +942,8 @@ golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= golang.org/x/tools v0.12.0 h1:YW6HUoUmYBpwSgyaGaZq1fHjrBjX1rlpZ54T6mu2kss= golang.org/x/tools v0.12.0/go.mod h1:Sc0INKfu04TlqNoRA1hgpFZbhYXHPr4V5DzpSBTPqQM= +golang.org/x/tools v0.14.0 h1:jvNa2pY0M4r62jkRQ6RwEZZyPcymeL9XZMLBbV7U2nc= +golang.org/x/tools v0.14.0/go.mod h1:uYBEerGOWcJyEORxN+Ek8+TT266gXkNlHdJBwexUsBg= 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= diff --git a/pkg/common/glob/glob.go b/pkg/common/glob/glob.go index a31bbe6fce70..9299a980170f 100644 --- a/pkg/common/glob/glob.go +++ b/pkg/common/glob/glob.go @@ -1,4 +1,4 @@ -package common +package glob import ( "fmt" diff --git a/pkg/common/glob/glob_test.go b/pkg/common/glob/glob_test.go index 32a445177964..3fd057fae0fa 100644 --- a/pkg/common/glob/glob_test.go +++ b/pkg/common/glob/glob_test.go @@ -1,4 +1,4 @@ -package common +package glob import ( "testing" diff --git a/pkg/decoders/base64.go b/pkg/decoders/base64.go index 6aa1f2c93198..56b46409e341 100644 --- a/pkg/decoders/base64.go +++ b/pkg/decoders/base64.go @@ -4,6 +4,7 @@ import ( "bytes" "encoding/base64" + "github.com/trufflesecurity/trufflehog/v3/pkg/pb/detectorspb" "github.com/trufflesecurity/trufflehog/v3/pkg/sources" ) @@ -25,7 +26,8 @@ func init() { } } -func (d *Base64) FromChunk(chunk *sources.Chunk) *sources.Chunk { +func (d *Base64) FromChunk(chunk *sources.Chunk) *DecodableChunk { + decodableChunk := &DecodableChunk{Chunk: chunk, DecoderType: detectorspb.DecoderType_BASE64} encodedSubstrings := getSubstringsOfCharacterSet(chunk.Data, 20, b64CharsetMapping, b64EndChars) decodedSubstrings := make(map[string][]byte) @@ -61,7 +63,7 @@ func (d *Base64) FromChunk(chunk *sources.Chunk) *sources.Chunk { } result.Write(chunk.Data[start:]) chunk.Data = result.Bytes() - return chunk + return decodableChunk } return nil diff --git a/pkg/decoders/decoders.go b/pkg/decoders/decoders.go index 52b4709e0cc7..b5e4768996e7 100644 --- a/pkg/decoders/decoders.go +++ b/pkg/decoders/decoders.go @@ -1,6 +1,7 @@ package decoders import ( + "github.com/trufflesecurity/trufflehog/v3/pkg/pb/detectorspb" "github.com/trufflesecurity/trufflehog/v3/pkg/sources" ) @@ -13,8 +14,15 @@ func DefaultDecoders() []Decoder { } } +// DecodableChunk is a chunk that includes the type of decoder used. +// This allows us to avoid a type assertion on each decoder. +type DecodableChunk struct { + *sources.Chunk + DecoderType detectorspb.DecoderType +} + type Decoder interface { - FromChunk(chunk *sources.Chunk) *sources.Chunk + FromChunk(chunk *sources.Chunk) *DecodableChunk } // Fuzz is an entrypoint for go-fuzz, which is an AFL-style fuzzing tool. diff --git a/pkg/decoders/utf16.go b/pkg/decoders/utf16.go index d5599a520ac0..c534b5812749 100644 --- a/pkg/decoders/utf16.go +++ b/pkg/decoders/utf16.go @@ -5,22 +5,24 @@ import ( "encoding/binary" "unicode/utf8" + "github.com/trufflesecurity/trufflehog/v3/pkg/pb/detectorspb" "github.com/trufflesecurity/trufflehog/v3/pkg/sources" ) type UTF16 struct{} -func (d *UTF16) FromChunk(chunk *sources.Chunk) *sources.Chunk { +func (d *UTF16) FromChunk(chunk *sources.Chunk) *DecodableChunk { if chunk == nil || len(chunk.Data) == 0 { return nil } + decodableChunk := &DecodableChunk{Chunk: chunk, DecoderType: detectorspb.DecoderType_UTF16} if utf16Data, err := utf16ToUTF8(chunk.Data); err == nil { if len(utf16Data) == 0 { return nil } chunk.Data = utf16Data - return chunk + return decodableChunk } return nil diff --git a/pkg/decoders/utf8.go b/pkg/decoders/utf8.go index 93090e71febe..be4c22dfab80 100644 --- a/pkg/decoders/utf8.go +++ b/pkg/decoders/utf8.go @@ -4,22 +4,25 @@ import ( "bytes" "unicode/utf8" + "github.com/trufflesecurity/trufflehog/v3/pkg/pb/detectorspb" "github.com/trufflesecurity/trufflehog/v3/pkg/sources" ) type UTF8 struct{} -func (d *UTF8) FromChunk(chunk *sources.Chunk) *sources.Chunk { +func (d *UTF8) FromChunk(chunk *sources.Chunk) *DecodableChunk { if chunk == nil || len(chunk.Data) == 0 { return nil } + decodableChunk := &DecodableChunk{Chunk: chunk, DecoderType: detectorspb.DecoderType_PLAIN} + if !utf8.Valid(chunk.Data) { chunk.Data = extractSubstrings(chunk.Data) - return chunk + return decodableChunk } - return chunk + return decodableChunk } // extractSubstrings performs similarly to the strings binutil, diff --git a/pkg/detectors/cloudsmith/cloudsmith.go b/pkg/detectors/cloudsmith/cloudsmith.go index 9ddc3b53e59d..b7aab4f6d097 100644 --- a/pkg/detectors/cloudsmith/cloudsmith.go +++ b/pkg/detectors/cloudsmith/cloudsmith.go @@ -2,6 +2,7 @@ package cloudsmith import ( "context" + "encoding/json" "net/http" "regexp" "strings" @@ -29,6 +30,10 @@ func (s Scanner) Keywords() []string { return []string{"cloudsmith"} } +type response struct { + Authenticated bool `json:"authenticated"` +} + // FromData will find and optionally verify Cloudsmith secrets in a given set of bytes. func (s Scanner) FromData(ctx context.Context, verify bool, data []byte) (results []detectors.Result, err error) { dataStr := string(data) @@ -57,7 +62,14 @@ func (s Scanner) FromData(ctx context.Context, verify bool, data []byte) (result if err == nil { defer res.Body.Close() if res.StatusCode >= 200 && res.StatusCode < 300 { - s1.Verified = true + var r response + if err := json.NewDecoder(res.Body).Decode(&r); err != nil { + s1.VerificationError = err + continue + } + if r.Authenticated { + s1.Verified = true + } } else { // This function will check false positives for common test words, but also it will make sure the key appears 'random' enough to be a real key. if detectors.IsKnownFalsePositive(resMatch, detectors.DefaultFalsePositives, true) { diff --git a/pkg/detectors/codeclimate/codeclimate.go b/pkg/detectors/codeclimate/codeclimate.go index 5820ad333717..aaf23de10517 100644 --- a/pkg/detectors/codeclimate/codeclimate.go +++ b/pkg/detectors/codeclimate/codeclimate.go @@ -2,6 +2,7 @@ package codeclimate import ( "context" + "encoding/json" "fmt" "net/http" "regexp" @@ -30,6 +31,12 @@ func (s Scanner) Keywords() []string { return []string{"codeclimate"} } +type response struct { + Data struct { + Id string `json:"id"` + } `json:"data"` +} + // FromData will find and optionally verify Codeclimate secrets in a given set of bytes. func (s Scanner) FromData(ctx context.Context, verify bool, data []byte) (results []detectors.Result, err error) { dataStr := string(data) @@ -58,7 +65,14 @@ func (s Scanner) FromData(ctx context.Context, verify bool, data []byte) (result if err == nil { defer res.Body.Close() if res.StatusCode >= 200 && res.StatusCode < 300 { - s1.Verified = true + var r response + if err := json.NewDecoder(res.Body).Decode(&r); err != nil { + s1.VerificationError = err + continue + } + if r.Data.Id != "" { + s1.Verified = true + } } else { // This function will check false positives for common test words, but also it will make sure the key appears 'random' enough to be a real key if detectors.IsKnownFalsePositive(resMatch, detectors.DefaultFalsePositives, true) { diff --git a/pkg/detectors/facebookoauth/facebookoauth.go b/pkg/detectors/facebookoauth/facebookoauth.go index a095ef9477ef..6fe5d2e80317 100644 --- a/pkg/detectors/facebookoauth/facebookoauth.go +++ b/pkg/detectors/facebookoauth/facebookoauth.go @@ -59,7 +59,8 @@ func (s Scanner) FromData(ctx context.Context, verify bool, data []byte) (result if verify { // thanks https://stackoverflow.com/questions/15621471/validate-a-facebook-app-id-and-app-secret - req, err := http.NewRequestWithContext(ctx, "GET", fmt.Sprintf("https://graph.facebook.com/%s?fields=roles&access_token=%s|%s", apiIdRes, apiIdRes, apiSecretRes), nil) + // https://stackoverflow.com/questions/24401241/how-to-get-a-facebook-access-token-using-appid-and-app-secret-without-any-login + req, err := http.NewRequestWithContext(ctx, "GET", fmt.Sprintf("https://graph.facebook.com/me?access_token=%s|%s", apiIdRes, apiSecretRes), nil) if err != nil { continue } diff --git a/pkg/detectors/flowdock/flowdock.go b/pkg/detectors/flowdock/flowdock.go deleted file mode 100644 index a648113a1496..000000000000 --- a/pkg/detectors/flowdock/flowdock.go +++ /dev/null @@ -1,77 +0,0 @@ -package flowdock - -import ( - "context" - "net/http" - "regexp" - "strings" - - "github.com/trufflesecurity/trufflehog/v3/pkg/common" - "github.com/trufflesecurity/trufflehog/v3/pkg/detectors" - "github.com/trufflesecurity/trufflehog/v3/pkg/pb/detectorspb" -) - -type Scanner struct{} - -// Ensure the Scanner satisfies the interface at compile time. -var _ detectors.Detector = (*Scanner)(nil) - -var ( - client = common.SaneHttpClient() - - // Make sure that your group is surrounded in boundary characters such as below to reduce false positives. - keyPat = regexp.MustCompile(detectors.PrefixRegex([]string{"flowdock"}) + `\b([0-9a-f]{32})\b`) -) - -// Keywords are used for efficiently pre-filtering chunks. -// Use identifiers in the secret preferably, or the provider name. -func (s Scanner) Keywords() []string { - return []string{"flowdock"} -} - -// FromData will find and optionally verify Flowdock secrets in a given set of bytes. -func (s Scanner) FromData(ctx context.Context, verify bool, data []byte) (results []detectors.Result, err error) { - dataStr := string(data) - - matches := keyPat.FindAllStringSubmatch(dataStr, -1) - - for _, match := range matches { - if len(match) != 2 { - continue - } - resMatch := strings.TrimSpace(match[1]) - - s1 := detectors.Result{ - DetectorType: detectorspb.DetectorType_Flowdock, - Raw: []byte(resMatch), - } - - if verify { - req, err := http.NewRequestWithContext(ctx, "GET", "https://api.flowdock.com/flows?users=false", nil) - if err != nil { - continue - } - req.SetBasicAuth(resMatch, "") - res, err := client.Do(req) - if err == nil { - defer res.Body.Close() - if res.StatusCode >= 200 && res.StatusCode < 300 { - s1.Verified = true - } else { - // This function will check false positives for common test words, but also it will make sure the key appears 'random' enough to be a real key. - if detectors.IsKnownFalsePositive(resMatch, detectors.DefaultFalsePositives, true) { - continue - } - } - } - } - - results = append(results, s1) - } - - return results, nil -} - -func (s Scanner) Type() detectorspb.DetectorType { - return detectorspb.DetectorType_Flowdock -} diff --git a/pkg/detectors/glitterlyapi/glitterlyapi.go b/pkg/detectors/glitterlyapi/glitterlyapi.go deleted file mode 100644 index bdd76b4e8344..000000000000 --- a/pkg/detectors/glitterlyapi/glitterlyapi.go +++ /dev/null @@ -1,78 +0,0 @@ -package glitterlyapi - -import ( - "context" - "net/http" - "regexp" - "strings" - - "github.com/trufflesecurity/trufflehog/v3/pkg/common" - "github.com/trufflesecurity/trufflehog/v3/pkg/detectors" - "github.com/trufflesecurity/trufflehog/v3/pkg/pb/detectorspb" -) - -type Scanner struct{} - -// Ensure the Scanner satisfies the interface at compile time. -var _ detectors.Detector = (*Scanner)(nil) - -var ( - client = common.SaneHttpClient() - - // Make sure that your group is surrounded in boundary characters such as below to reduce false positives. - keyPat = regexp.MustCompile(detectors.PrefixRegex([]string{"glitterlyapi"}) + `\b([0-9a-z-]{36})\b`) -) - -// Keywords are used for efficiently pre-filtering chunks. -// Use identifiers in the secret preferably, or the provider name. -func (s Scanner) Keywords() []string { - return []string{"glitterlyapi"} -} - -// FromData will find and optionally verify GlitterlyAPI secrets in a given set of bytes. -func (s Scanner) FromData(ctx context.Context, verify bool, data []byte) (results []detectors.Result, err error) { - dataStr := string(data) - - matches := keyPat.FindAllStringSubmatch(dataStr, -1) - - for _, match := range matches { - if len(match) != 2 { - continue - } - resMatch := strings.TrimSpace(match[1]) - - s1 := detectors.Result{ - DetectorType: detectorspb.DetectorType_GlitterlyAPI, - Raw: []byte(resMatch), - } - - if verify { - req, err := http.NewRequestWithContext(ctx, "GET", "https://www.glitterlyapi.com/auth", nil) - if err != nil { - continue - } - req.Header.Add("Content-Type", "application/json") - req.Header.Add("x-api-key", resMatch) - res, err := client.Do(req) - if err == nil { - defer res.Body.Close() - if res.StatusCode >= 200 && res.StatusCode < 300 { - s1.Verified = true - } else { - // This function will check false positives for common test words, but also it will make sure the key appears 'random' enough to be a real key. - if detectors.IsKnownFalsePositive(resMatch, detectors.DefaultFalsePositives, true) { - continue - } - } - } - } - - results = append(results, s1) - } - - return results, nil -} - -func (s Scanner) Type() detectorspb.DetectorType { - return detectorspb.DetectorType_GlitterlyAPI -} diff --git a/pkg/detectors/glitterlyapi/glitterlyapi_test.go b/pkg/detectors/glitterlyapi/glitterlyapi_test.go deleted file mode 100644 index be54b8fd5754..000000000000 --- a/pkg/detectors/glitterlyapi/glitterlyapi_test.go +++ /dev/null @@ -1,120 +0,0 @@ -//go:build detectors -// +build detectors - -package glitterlyapi - -import ( - "context" - "fmt" - "testing" - "time" - - "github.com/kylelemons/godebug/pretty" - "github.com/trufflesecurity/trufflehog/v3/pkg/detectors" - - "github.com/trufflesecurity/trufflehog/v3/pkg/common" - "github.com/trufflesecurity/trufflehog/v3/pkg/pb/detectorspb" -) - -func TestGlitterlyAPI_FromChunk(t *testing.T) { - ctx, cancel := context.WithTimeout(context.Background(), time.Second*5) - defer cancel() - testSecrets, err := common.GetSecret(ctx, "trufflehog-testing", "detectors3") - if err != nil { - t.Fatalf("could not get test secrets from GCP: %s", err) - } - secret := testSecrets.MustGetField("GLITTERLYAPI") - inactiveSecret := testSecrets.MustGetField("GLITTERLYAPI_INACTIVE") - - type args struct { - ctx context.Context - data []byte - verify bool - } - tests := []struct { - name string - s Scanner - args args - want []detectors.Result - wantErr bool - }{ - { - name: "found, verified", - s: Scanner{}, - args: args{ - ctx: context.Background(), - data: []byte(fmt.Sprintf("You can find a glitterlyapi secret %s within", secret)), - verify: true, - }, - want: []detectors.Result{ - { - DetectorType: detectorspb.DetectorType_GlitterlyAPI, - Verified: true, - }, - }, - wantErr: false, - }, - { - name: "found, unverified", - s: Scanner{}, - args: args{ - ctx: context.Background(), - data: []byte(fmt.Sprintf("You can find a glitterlyapi secret %s within but not valid", inactiveSecret)), // the secret would satisfy the regex but not pass validation - verify: true, - }, - want: []detectors.Result{ - { - DetectorType: detectorspb.DetectorType_GlitterlyAPI, - Verified: false, - }, - }, - wantErr: false, - }, - { - name: "not found", - s: Scanner{}, - args: args{ - ctx: context.Background(), - data: []byte("You cannot find the secret within"), - verify: true, - }, - want: nil, - wantErr: false, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - s := Scanner{} - got, err := s.FromData(tt.args.ctx, tt.args.verify, tt.args.data) - if (err != nil) != tt.wantErr { - t.Errorf("GlitterlyAPI.FromData() error = %v, wantErr %v", err, tt.wantErr) - return - } - for i := range got { - if len(got[i].Raw) == 0 { - t.Fatalf("no raw secret present: \n %+v", got[i]) - } - got[i].Raw = nil - } - if diff := pretty.Compare(got, tt.want); diff != "" { - t.Errorf("GlitterlyAPI.FromData() %s diff: (-got +want)\n%s", tt.name, diff) - } - }) - } -} - -func BenchmarkFromData(benchmark *testing.B) { - ctx := context.Background() - s := Scanner{} - for name, data := range detectors.MustGetBenchmarkData() { - benchmark.Run(name, func(b *testing.B) { - b.ResetTimer() - for n := 0; n < b.N; n++ { - _, err := s.FromData(ctx, false, data) - if err != nil { - b.Fatal(err) - } - } - }) - } -} diff --git a/pkg/detectors/happi/happi.go b/pkg/detectors/happi/happi.go deleted file mode 100644 index 4fb6cebfcf13..000000000000 --- a/pkg/detectors/happi/happi.go +++ /dev/null @@ -1,77 +0,0 @@ -package happi - -import ( - "context" - "net/http" - "regexp" - "strings" - - "github.com/trufflesecurity/trufflehog/v3/pkg/common" - "github.com/trufflesecurity/trufflehog/v3/pkg/detectors" - "github.com/trufflesecurity/trufflehog/v3/pkg/pb/detectorspb" -) - -type Scanner struct{} - -// Ensure the Scanner satisfies the interface at compile time. -var _ detectors.Detector = (*Scanner)(nil) - -var ( - client = common.SaneHttpClient() - - // Make sure that your group is surrounded in boundary characters such as below to reduce false positives. - keyPat = regexp.MustCompile(detectors.PrefixRegex([]string{"happi"}) + `\b([a-zA-Z0-9]{56})`) -) - -// Keywords are used for efficiently pre-filtering chunks. -// Use identifiers in the secret preferably, or the provider name. -func (s Scanner) Keywords() []string { - return []string{"happi"} -} - -// FromData will find and optionally verify Happi secrets in a given set of bytes. -func (s Scanner) FromData(ctx context.Context, verify bool, data []byte) (results []detectors.Result, err error) { - dataStr := string(data) - - matches := keyPat.FindAllStringSubmatch(dataStr, -1) - - for _, match := range matches { - if len(match) != 2 { - continue - } - resMatch := strings.TrimSpace(match[1]) - - s1 := detectors.Result{ - DetectorType: detectorspb.DetectorType_Happi, - Raw: []byte(resMatch), - } - - if verify { - req, err := http.NewRequestWithContext(ctx, "GET", "https://api.happi.dev/v1/exchange", nil) - if err != nil { - continue - } - req.Header.Add("x-happi-key", resMatch) - res, err := client.Do(req) - if err == nil { - defer res.Body.Close() - if res.StatusCode >= 200 && res.StatusCode < 300 { - s1.Verified = true - } else { - // This function will check false positives for common test words, but also it will make sure the key appears 'random' enough to be a real key. - if detectors.IsKnownFalsePositive(resMatch, detectors.DefaultFalsePositives, true) { - continue - } - } - } - } - - results = append(results, s1) - } - - return results, nil -} - -func (s Scanner) Type() detectorspb.DetectorType { - return detectorspb.DetectorType_Happi -} diff --git a/pkg/detectors/happi/happi_test.go b/pkg/detectors/happi/happi_test.go deleted file mode 100644 index fd6bc1b56761..000000000000 --- a/pkg/detectors/happi/happi_test.go +++ /dev/null @@ -1,120 +0,0 @@ -//go:build detectors -// +build detectors - -package happi - -import ( - "context" - "fmt" - "testing" - "time" - - "github.com/kylelemons/godebug/pretty" - "github.com/trufflesecurity/trufflehog/v3/pkg/detectors" - - "github.com/trufflesecurity/trufflehog/v3/pkg/common" - "github.com/trufflesecurity/trufflehog/v3/pkg/pb/detectorspb" -) - -func TestHappi_FromChunk(t *testing.T) { - ctx, cancel := context.WithTimeout(context.Background(), time.Second*5) - defer cancel() - testSecrets, err := common.GetSecret(ctx, "trufflehog-testing", "detectors2") - if err != nil { - t.Fatalf("could not get test secrets from GCP: %s", err) - } - secret := testSecrets.MustGetField("HAPPI") - inactiveSecret := testSecrets.MustGetField("HAPPI_INACTIVE") - - type args struct { - ctx context.Context - data []byte - verify bool - } - tests := []struct { - name string - s Scanner - args args - want []detectors.Result - wantErr bool - }{ - { - name: "found, verified", - s: Scanner{}, - args: args{ - ctx: context.Background(), - data: []byte(fmt.Sprintf("You can find a happi secret %s within", secret)), - verify: true, - }, - want: []detectors.Result{ - { - DetectorType: detectorspb.DetectorType_Happi, - Verified: true, - }, - }, - wantErr: false, - }, - { - name: "found, unverified", - s: Scanner{}, - args: args{ - ctx: context.Background(), - data: []byte(fmt.Sprintf("You can find a happi secret %s within but not valid", inactiveSecret)), // the secret would satisfy the regex but not pass validation - verify: true, - }, - want: []detectors.Result{ - { - DetectorType: detectorspb.DetectorType_Happi, - Verified: false, - }, - }, - wantErr: false, - }, - { - name: "not found", - s: Scanner{}, - args: args{ - ctx: context.Background(), - data: []byte("You cannot find the secret within"), - verify: true, - }, - want: nil, - wantErr: false, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - s := Scanner{} - got, err := s.FromData(tt.args.ctx, tt.args.verify, tt.args.data) - if (err != nil) != tt.wantErr { - t.Errorf("Happi.FromData() error = %v, wantErr %v", err, tt.wantErr) - return - } - for i := range got { - if len(got[i].Raw) == 0 { - t.Fatalf("no raw secret present: \n %+v", got[i]) - } - got[i].Raw = nil - } - if diff := pretty.Compare(got, tt.want); diff != "" { - t.Errorf("Happi.FromData() %s diff: (-got +want)\n%s", tt.name, diff) - } - }) - } -} - -func BenchmarkFromData(benchmark *testing.B) { - ctx := context.Background() - s := Scanner{} - for name, data := range detectors.MustGetBenchmarkData() { - benchmark.Run(name, func(b *testing.B) { - b.ResetTimer() - for n := 0; n < b.N; n++ { - _, err := s.FromData(ctx, false, data) - if err != nil { - b.Fatal(err) - } - } - }) - } -} diff --git a/pkg/detectors/instamojo/instamojo.go b/pkg/detectors/instamojo/instamojo.go new file mode 100644 index 000000000000..4ada2694ad06 --- /dev/null +++ b/pkg/detectors/instamojo/instamojo.go @@ -0,0 +1,105 @@ +package instamojo + +import ( + "context" + "fmt" + "io" + "net/http" + "regexp" + "strings" + + "github.com/trufflesecurity/trufflehog/v3/pkg/common" + "github.com/trufflesecurity/trufflehog/v3/pkg/detectors" + "github.com/trufflesecurity/trufflehog/v3/pkg/pb/detectorspb" +) + +type Scanner struct { + client *http.Client +} + +// Ensure the Scanner satisfies the interface at compile time. +var _ detectors.Detector = (*Scanner)(nil) + +var ( + defaultClient = common.SaneHttpClient() + // Make sure that your group is surrounded in boundary characters such as below to reduce false positives. + //KeyPat is client_id + keyPat = regexp.MustCompile(detectors.PrefixRegex([]string{"instamojo"}) + `\b([0-9a-zA-Z]{40})\b`) + //Secretpat is Client_secret + secretPat = regexp.MustCompile(detectors.PrefixRegex([]string{"instamojo"}) + `\b([0-9a-zA-Z]{128})\b`) +) + +// Keywords are used for efficiently pre-filtering chunks. +// Use identifiers in the secret preferably, or the provider name. +func (s Scanner) Keywords() []string { + return []string{"instamojo"} +} + +// FromData will find and optionally verify Instamojo secrets in a given set of bytes. +func (s Scanner) FromData(ctx context.Context, verify bool, data []byte) (results []detectors.Result, err error) { + dataStr := string(data) + + secretMatches := secretPat.FindAllStringSubmatch(dataStr, -1) + clientIdmatches := keyPat.FindAllStringSubmatch(dataStr, -1) + + for _, match := range secretMatches { + if len(match) != 2 { + continue + } + resSecret := strings.TrimSpace(match[1]) + + for _, clientIdMatch := range clientIdmatches { + if len(clientIdMatch) != 2 { + continue + } + resClientId := strings.TrimSpace(clientIdMatch[1]) + + s1 := detectors.Result{ + DetectorType: detectorspb.DetectorType_Instamojo, + Raw: []byte(resClientId), + } + + if verify { + client := s.client + if client == nil { + client = defaultClient + } + payload := strings.NewReader("grant_type=client_credentials&client_id=" + resClientId + "&client_secret=" + resSecret) + + req, err := http.NewRequestWithContext(ctx, "POST", "https://api.instamojo.com/oauth2/token/", payload) + if err != nil { + continue + } + req.Header.Add("Content-Type", "application/x-www-form-urlencoded") + res, err := client.Do(req) + if err == nil { + defer res.Body.Close() + bodyBytes, err := io.ReadAll(res.Body) + if err != nil { + continue + } + body := string(bodyBytes) + if (res.StatusCode >= 200 && res.StatusCode < 300) && strings.Contains(body, "access_token") { + s1.Verified = true + } else { + s1.VerificationError = fmt.Errorf("unexpected HTTP response status %d", res.StatusCode) + } + } else { + s1.VerificationError = err + } + } + + if !s1.Verified && detectors.IsKnownFalsePositive(string(s1.Raw), detectors.DefaultFalsePositives, true) { + continue + } + + results = append(results, s1) + } + } + + return results, nil +} + +func (s Scanner) Type() detectorspb.DetectorType { + return detectorspb.DetectorType_Instamojo +} diff --git a/pkg/detectors/blablabus/blablabus_test.go b/pkg/detectors/instamojo/instamojo_test.go similarity index 59% rename from pkg/detectors/blablabus/blablabus_test.go rename to pkg/detectors/instamojo/instamojo_test.go index f2d987b572a0..d6e6fdb36a6a 100644 --- a/pkg/detectors/blablabus/blablabus_test.go +++ b/pkg/detectors/instamojo/instamojo_test.go @@ -1,7 +1,7 @@ //go:build detectors // +build detectors -package blablabus +package instamojo import ( "context" @@ -16,15 +16,16 @@ import ( "github.com/trufflesecurity/trufflehog/v3/pkg/pb/detectorspb" ) -func TestBlablabus_FromChunk(t *testing.T) { +func TestInstamojo_FromChunk(t *testing.T) { ctx, cancel := context.WithTimeout(context.Background(), time.Second*5) defer cancel() - testSecrets, err := common.GetSecret(ctx, "trufflehog-testing", "detectors1") + testSecrets, err := common.GetSecret(ctx, "trufflehog-testing", "detectors5") if err != nil { t.Fatalf("could not get test secrets from GCP: %s", err) } - secret := testSecrets.MustGetField("BLABLABUS") - inactiveSecret := testSecrets.MustGetField("BLABLABUS_INACTIVE") + id := testSecrets.MustGetField("INSTAMOJO_CLIENT_ID") + secret := testSecrets.MustGetField("INSTAMOJO_SECRET") + inactiveSecret := testSecrets.MustGetField("INSTAMOJO_INACTIVE") type args struct { ctx context.Context @@ -32,43 +33,46 @@ func TestBlablabus_FromChunk(t *testing.T) { verify bool } tests := []struct { - name string - s Scanner - args args - want []detectors.Result - wantErr bool + name string + s Scanner + args args + want []detectors.Result + wantErr bool + wantVerificationErr bool }{ { name: "found, verified", s: Scanner{}, args: args{ ctx: context.Background(), - data: []byte(fmt.Sprintf("You can find a blablabus secret %s within", secret)), + data: []byte(fmt.Sprintf("You can find a instamojo secret %s within id %s", secret, id)), verify: true, }, want: []detectors.Result{ { - DetectorType: detectorspb.DetectorType_Blablabus, + DetectorType: detectorspb.DetectorType_Instamojo, Verified: true, }, }, - wantErr: false, + wantErr: false, + wantVerificationErr: false, }, { name: "found, unverified", s: Scanner{}, args: args{ ctx: context.Background(), - data: []byte(fmt.Sprintf("You can find a blablabus secret %s within but not valid", inactiveSecret)), // the secret would satisfy the regex but not pass validation + data: []byte(fmt.Sprintf("You can find a instamojo secret %s within but not valid, within id %s", inactiveSecret, id)), // the secret would satisfy the regex but not pass validation verify: true, }, want: []detectors.Result{ { - DetectorType: detectorspb.DetectorType_Blablabus, - Verified: false, + DetectorType: detectorspb.DetectorType_Instamojo, + VerificationError: fmt.Errorf("unexpected HTTP response status 401"), }, }, - wantErr: false, + wantErr: false, + wantVerificationErr: true, }, { name: "not found", @@ -78,16 +82,16 @@ func TestBlablabus_FromChunk(t *testing.T) { data: []byte("You cannot find the secret within"), verify: true, }, - want: nil, - wantErr: false, + want: nil, + wantErr: false, + wantVerificationErr: true, }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - s := Scanner{} - got, err := s.FromData(tt.args.ctx, tt.args.verify, tt.args.data) + got, err := tt.s.FromData(tt.args.ctx, tt.args.verify, tt.args.data) if (err != nil) != tt.wantErr { - t.Errorf("Blablabus.FromData() error = %v, wantErr %v", err, tt.wantErr) + t.Errorf("Instamojo.FromData() error = %v, wantErr %v", err, tt.wantErr) return } for i := range got { @@ -97,7 +101,7 @@ func TestBlablabus_FromChunk(t *testing.T) { got[i].Raw = nil } if diff := pretty.Compare(got, tt.want); diff != "" { - t.Errorf("Blablabus.FromData() %s diff: (-got +want)\n%s", tt.name, diff) + t.Errorf("Instamojo.FromData() %s diff: (-got +want)\n%s", tt.name, diff) } }) } diff --git a/pkg/detectors/datafire/datafire.go b/pkg/detectors/ip2location/ip2location.go similarity index 65% rename from pkg/detectors/datafire/datafire.go rename to pkg/detectors/ip2location/ip2location.go index 1ef956490eff..9503b51e098d 100644 --- a/pkg/detectors/datafire/datafire.go +++ b/pkg/detectors/ip2location/ip2location.go @@ -1,4 +1,4 @@ -package datafire +package ip2location import ( "context" @@ -12,25 +12,24 @@ import ( "github.com/trufflesecurity/trufflehog/v3/pkg/pb/detectorspb" ) -type Scanner struct{} +type Scanner struct {} // Ensure the Scanner satisfies the interface at compile time. var _ detectors.Detector = (*Scanner)(nil) var ( client = common.SaneHttpClient() - // Make sure that your group is surrounded in boundary characters such as below to reduce false positives. - keyPat = regexp.MustCompile(detectors.PrefixRegex([]string{"datafire"}) + `\b([a-z0-9\S]{175,190})\b`) + keyPat = regexp.MustCompile(detectors.PrefixRegex([]string{"ip2location"}) + `\b([0-9A-Z]{32})\b`) ) // Keywords are used for efficiently pre-filtering chunks. // Use identifiers in the secret preferably, or the provider name. func (s Scanner) Keywords() []string { - return []string{"datafire"} + return []string{"ip2location"} } -// FromData will find and optionally verify DataFire secrets in a given set of bytes. +// FromData will find and optionally verify Ip2location secrets in a given set of bytes. func (s Scanner) FromData(ctx context.Context, verify bool, data []byte) (results []detectors.Result, err error) { dataStr := string(data) @@ -43,29 +42,33 @@ func (s Scanner) FromData(ctx context.Context, verify bool, data []byte) (result resMatch := strings.TrimSpace(match[1]) s1 := detectors.Result{ - DetectorType: detectorspb.DetectorType_DataFire, + DetectorType: detectorspb.DetectorType_Ip2location, Raw: []byte(resMatch), } if verify { - req, err := http.NewRequestWithContext(ctx, "GET", "https://api.datafire.io/projects/", nil) + req, err := http.NewRequestWithContext(ctx, "GET", "https://api.ip2location.io/?key=" + resMatch, nil) + if err != nil { continue } - req.Header.Add("Authorization", fmt.Sprintf("Bearer %s", resMatch)) res, err := client.Do(req) if err == nil { defer res.Body.Close() if res.StatusCode >= 200 && res.StatusCode < 300 { s1.Verified = true + } else if res.StatusCode == 401 { + // The secret is determinately not verified (nothing to do) } else { - // This function will check false positives for common test words, but also it will make sure the key appears 'random' enough to be a real key. - if detectors.IsKnownFalsePositive(resMatch, detectors.DefaultFalsePositives, true) { - continue - } + s1.VerificationError = fmt.Errorf("unexpected HTTP response status %d", res.StatusCode) } + } else { + s1.VerificationError = err } } + if !s1.Verified && detectors.IsKnownFalsePositive(resMatch, detectors.DefaultFalsePositives, true) { + continue + } results = append(results, s1) } @@ -74,5 +77,8 @@ func (s Scanner) FromData(ctx context.Context, verify bool, data []byte) (result } func (s Scanner) Type() detectorspb.DetectorType { - return detectorspb.DetectorType_DataFire + return detectorspb.DetectorType_Ip2location } + + + diff --git a/pkg/detectors/flowdock/flowdock_test.go b/pkg/detectors/ip2location/ip2location_test.go similarity index 52% rename from pkg/detectors/flowdock/flowdock_test.go rename to pkg/detectors/ip2location/ip2location_test.go index 9c9aa78c2598..caf61edbd683 100644 --- a/pkg/detectors/flowdock/flowdock_test.go +++ b/pkg/detectors/ip2location/ip2location_test.go @@ -1,7 +1,7 @@ //go:build detectors // +build detectors -package flowdock +package ip2location import ( "context" @@ -9,22 +9,24 @@ import ( "testing" "time" - "github.com/kylelemons/godebug/pretty" + "github.com/google/go-cmp/cmp" + "github.com/google/go-cmp/cmp/cmpopts" + "github.com/trufflesecurity/trufflehog/v3/pkg/detectors" "github.com/trufflesecurity/trufflehog/v3/pkg/common" "github.com/trufflesecurity/trufflehog/v3/pkg/pb/detectorspb" ) -func TestFlowdock_FromChunk(t *testing.T) { +func TestIp2location_FromChunk(t *testing.T) { ctx, cancel := context.WithTimeout(context.Background(), time.Second*5) defer cancel() - testSecrets, err := common.GetSecret(ctx, "trufflehog-testing", "detectors3") + testSecrets, err := common.GetSecret(ctx, "trufflehog-testing", "detectors5") if err != nil { t.Fatalf("could not get test secrets from GCP: %s", err) } - secret := testSecrets.MustGetField("FLOWDOCK") - inactiveSecret := testSecrets.MustGetField("FLOWDOCK_INACTIVE") + secret := testSecrets.MustGetField("IP2LOCATION") + inactiveSecret := testSecrets.MustGetField("IP2LOCATION_INACTIVE") type args struct { ctx context.Context @@ -32,43 +34,46 @@ func TestFlowdock_FromChunk(t *testing.T) { verify bool } tests := []struct { - name string - s Scanner - args args - want []detectors.Result - wantErr bool + name string + s Scanner + args args + want []detectors.Result + wantErr bool + wantVerificationErr bool }{ { name: "found, verified", s: Scanner{}, args: args{ ctx: context.Background(), - data: []byte(fmt.Sprintf("You can find a flowdock secret %s within", secret)), + data: []byte(fmt.Sprintf("You can find a ip2location secret %s within", secret)), verify: true, }, want: []detectors.Result{ { - DetectorType: detectorspb.DetectorType_Flowdock, + DetectorType: detectorspb.DetectorType_Ip2location, Verified: true, }, }, - wantErr: false, + wantErr: false, + wantVerificationErr: false, }, { name: "found, unverified", s: Scanner{}, args: args{ ctx: context.Background(), - data: []byte(fmt.Sprintf("You can find a flowdock secret %s within but not valid", inactiveSecret)), // the secret would satisfy the regex but not pass validation + data: []byte(fmt.Sprintf("You can find a ip2location secret %s within but not valid", inactiveSecret)), // the secret would satisfy the regex but not pass validation verify: true, }, want: []detectors.Result{ { - DetectorType: detectorspb.DetectorType_Flowdock, + DetectorType: detectorspb.DetectorType_Ip2location, Verified: false, }, }, - wantErr: false, + wantErr: false, + wantVerificationErr: false, }, { name: "not found", @@ -78,26 +83,29 @@ func TestFlowdock_FromChunk(t *testing.T) { data: []byte("You cannot find the secret within"), verify: true, }, - want: nil, - wantErr: false, + want: nil, + wantErr: false, + wantVerificationErr: false, }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - s := Scanner{} - got, err := s.FromData(tt.args.ctx, tt.args.verify, tt.args.data) + got, err := tt.s.FromData(tt.args.ctx, tt.args.verify, tt.args.data) if (err != nil) != tt.wantErr { - t.Errorf("Flowdock.FromData() error = %v, wantErr %v", err, tt.wantErr) + t.Errorf("Ip2location.FromData() error = %v, wantErr %v", err, tt.wantErr) return } for i := range got { if len(got[i].Raw) == 0 { t.Fatalf("no raw secret present: \n %+v", got[i]) } - got[i].Raw = nil + if (got[i].VerificationError != nil) != tt.wantVerificationErr { + t.Fatalf("wantVerificationError = %v, verification error = %v", tt.wantVerificationErr, got[i].VerificationError) + } } - if diff := pretty.Compare(got, tt.want); diff != "" { - t.Errorf("Flowdock.FromData() %s diff: (-got +want)\n%s", tt.name, diff) + ignoreOpts := cmpopts.IgnoreFields(detectors.Result{}, "Raw", "VerificationError") + if diff := cmp.Diff(got, tt.want, ignoreOpts); diff != "" { + t.Errorf("Ip2location.FromData() %s diff: (-got +want)\n%s", tt.name, diff) } }) } diff --git a/pkg/detectors/blablabus/blablabus.go b/pkg/detectors/ipinfo/ipinfo.go similarity index 54% rename from pkg/detectors/blablabus/blablabus.go rename to pkg/detectors/ipinfo/ipinfo.go index 9bca40925805..4b7024b33254 100644 --- a/pkg/detectors/blablabus/blablabus.go +++ b/pkg/detectors/ipinfo/ipinfo.go @@ -1,4 +1,4 @@ -package blablabus +package ipinfo import ( "context" @@ -12,25 +12,26 @@ import ( "github.com/trufflesecurity/trufflehog/v3/pkg/pb/detectorspb" ) -type Scanner struct{} +type Scanner struct { + client *http.Client +} // Ensure the Scanner satisfies the interface at compile time. var _ detectors.Detector = (*Scanner)(nil) var ( - client = common.SaneHttpClient() - + defaultClient = common.SaneHttpClient() // Make sure that your group is surrounded in boundary characters such as below to reduce false positives. - keyPat = regexp.MustCompile(detectors.PrefixRegex([]string{"blablabus"}) + `\b([0-9A-Za-z]{22})\b`) + keyPat = regexp.MustCompile(detectors.PrefixRegex([]string{"ipinfo"}) + `\b([a-f0-9]{14})\b`) ) // Keywords are used for efficiently pre-filtering chunks. // Use identifiers in the secret preferably, or the provider name. func (s Scanner) Keywords() []string { - return []string{"blablabus"} + return []string{"ipinfo"} } -// FromData will find and optionally verify Blablabus secrets in a given set of bytes. +// FromData will find and optionally verify Ipinfo secrets in a given set of bytes. func (s Scanner) FromData(ctx context.Context, verify bool, data []byte) (results []detectors.Result, err error) { dataStr := string(data) @@ -43,31 +44,40 @@ func (s Scanner) FromData(ctx context.Context, verify bool, data []byte) (result resMatch := strings.TrimSpace(match[1]) s1 := detectors.Result{ - DetectorType: detectorspb.DetectorType_Blablabus, + DetectorType: detectorspb.DetectorType_IPInfo, Raw: []byte(resMatch), } if verify { - req, err := http.NewRequestWithContext(ctx, "GET", "https://api.idbus.com/v3/stops", nil) + client := s.client + if client == nil { + client = defaultClient + } + req, err := http.NewRequestWithContext(ctx, "GET", "https://ipinfo.io/json?token="+resMatch, nil) if err != nil { continue } - req.Header.Add("Content-Type", "application/json") - req.Header.Add("Authorization", fmt.Sprintf("Token %s", resMatch)) res, err := client.Do(req) if err == nil { + fmt.Println(res.Status, resMatch) defer res.Body.Close() if res.StatusCode >= 200 && res.StatusCode < 300 { s1.Verified = true + } else if res.StatusCode == 403 { + // The secret is determinately not verified (nothing to do) } else { - // This function will check false positives for common test words, but also it will make sure the key appears 'random' enough to be a real key. - if detectors.IsKnownFalsePositive(resMatch, detectors.DefaultFalsePositives, true) { - continue - } + s1.VerificationError = fmt.Errorf("unexpected HTTP response status %d", res.StatusCode) } + } else { + s1.VerificationError = err } } + // This function will check false positives for common test words, but also it will make sure the key appears 'random' enough to be a real key. + if !s1.Verified && detectors.IsKnownFalsePositive(resMatch, detectors.DefaultFalsePositives, true) { + continue + } + results = append(results, s1) } @@ -75,5 +85,5 @@ func (s Scanner) FromData(ctx context.Context, verify bool, data []byte) (result } func (s Scanner) Type() detectorspb.DetectorType { - return detectorspb.DetectorType_Blablabus + return detectorspb.DetectorType_IPInfo } diff --git a/pkg/detectors/ipinfo/ipinfo_test.go b/pkg/detectors/ipinfo/ipinfo_test.go new file mode 100644 index 000000000000..d1c523fbec58 --- /dev/null +++ b/pkg/detectors/ipinfo/ipinfo_test.go @@ -0,0 +1,161 @@ +//go:build detectors +// +build detectors + +package ipinfo + +import ( + "context" + "fmt" + "github.com/google/go-cmp/cmp" + "github.com/google/go-cmp/cmp/cmpopts" + "testing" + "time" + + "github.com/trufflesecurity/trufflehog/v3/pkg/detectors" + + "github.com/trufflesecurity/trufflehog/v3/pkg/common" + "github.com/trufflesecurity/trufflehog/v3/pkg/pb/detectorspb" +) + +func TestIpinfo_FromChunk(t *testing.T) { + ctx, cancel := context.WithTimeout(context.Background(), time.Second*5) + defer cancel() + testSecrets, err := common.GetSecret(ctx, "trufflehog-testing", "detectors5") + if err != nil { + t.Fatalf("could not get test secrets from GCP: %s", err) + } + secret := testSecrets.MustGetField("IPINFO") + inactiveSecret := testSecrets.MustGetField("IPINFO_INACTIVE") + + type args struct { + ctx context.Context + data []byte + verify bool + } + tests := []struct { + name string + s Scanner + args args + want []detectors.Result + wantErr bool + wantVerificationErr bool + }{ + { + name: "found, verified", + s: Scanner{}, + args: args{ + ctx: context.Background(), + data: []byte(fmt.Sprintf("You can find a ipinfo secret %s within", secret)), + verify: true, + }, + want: []detectors.Result{ + { + DetectorType: detectorspb.DetectorType_IPInfo, + Verified: true, + }, + }, + wantErr: false, + wantVerificationErr: false, + }, + { + name: "found, unverified", + s: Scanner{}, + args: args{ + ctx: context.Background(), + data: []byte(fmt.Sprintf("You can find a ipinfo secret %s within but not valid", inactiveSecret)), // the secret would satisfy the regex but not pass validation + verify: true, + }, + want: []detectors.Result{ + { + DetectorType: detectorspb.DetectorType_IPInfo, + Verified: false, + }, + }, + wantErr: false, + wantVerificationErr: false, + }, + { + name: "not found", + s: Scanner{}, + args: args{ + ctx: context.Background(), + data: []byte("You cannot find the secret within"), + verify: true, + }, + want: nil, + wantErr: false, + wantVerificationErr: false, + }, + { + name: "found, would be verified if not for timeout", + s: Scanner{client: common.SaneHttpClientTimeOut(1 * time.Microsecond)}, + args: args{ + ctx: context.Background(), + data: []byte(fmt.Sprintf("You can find a ipinfo secret %s within", secret)), + verify: true, + }, + want: []detectors.Result{ + { + DetectorType: detectorspb.DetectorType_IPInfo, + Verified: false, + }, + }, + wantErr: false, + wantVerificationErr: true, + }, + { + name: "found, verified but unexpected api surface", + s: Scanner{client: common.ConstantResponseHttpClient(404, "")}, + args: args{ + ctx: context.Background(), + data: []byte(fmt.Sprintf("You can find a ipinfo secret %s within", secret)), + verify: true, + }, + want: []detectors.Result{ + { + DetectorType: detectorspb.DetectorType_IPInfo, + Verified: false, + }, + }, + wantErr: false, + wantVerificationErr: true, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got, err := tt.s.FromData(tt.args.ctx, tt.args.verify, tt.args.data) + if (err != nil) != tt.wantErr { + t.Errorf("Ipinfo.FromData() error = %v, wantErr %v", err, tt.wantErr) + return + } + for i := range got { + if len(got[i].Raw) == 0 { + t.Fatalf("no raw secret present: \n %+v", got[i]) + } + if (got[i].VerificationError != nil) != tt.wantVerificationErr { + t.Fatalf("wantVerificationError = %v, verification error = %v", tt.wantVerificationErr, got[i].VerificationError) + } + } + ignoreOpts := cmpopts.IgnoreFields(detectors.Result{}, "Raw", "VerificationError") + if diff := cmp.Diff(got, tt.want, ignoreOpts); diff != "" { + t.Errorf("Ipinfo.FromData() %s diff: (-got +want)\n%s", tt.name, diff) + } + }) + } +} + +func BenchmarkFromData(benchmark *testing.B) { + ctx := context.Background() + s := Scanner{} + for name, data := range detectors.MustGetBenchmarkData() { + benchmark.Run(name, func(b *testing.B) { + b.ResetTimer() + for n := 0; n < b.N; n++ { + _, err := s.FromData(ctx, false, data) + if err != nil { + b.Fatal(err) + } + } + }) + } +} diff --git a/pkg/detectors/loggly/loggly.go b/pkg/detectors/loggly/loggly.go new file mode 100644 index 000000000000..1c7bcd606644 --- /dev/null +++ b/pkg/detectors/loggly/loggly.go @@ -0,0 +1,101 @@ +package loggly + +import ( + "context" + "fmt" + "net/http" + "regexp" + "strings" + + "github.com/trufflesecurity/trufflehog/v3/pkg/common" + "github.com/trufflesecurity/trufflehog/v3/pkg/detectors" + "github.com/trufflesecurity/trufflehog/v3/pkg/pb/detectorspb" +) + +type Scanner struct { + client *http.Client +} + +// Ensure the Scanner satisfies the interface at compile time. +var _ detectors.Detector = (*Scanner)(nil) + +var ( + defaultClient = common.SaneHttpClient() + // Make sure that your group is surrounded in boundary characters such as below to reduce false positives. + domainPat = regexp.MustCompile(`\b([a-zA-Z0-9-]+\.loggly\.com)\b`) + keyPat = regexp.MustCompile(detectors.PrefixRegex([]string{"loggly"}) + `\b([a-z0-9]{8}-[a-z0-9]{4}-[a-z0-9]{4}-[a-z0-9]{4}-[a-z0-9]{12})\b`) +) + +// Keywords are used for efficiently pre-filtering chunks. +// Use identifiers in the secret preferably, or the provider name. +func (s Scanner) Keywords() []string { + return []string{"loggly"} +} + +// FromData will find and optionally verify Loggly secrets in a given set of bytes. +func (s Scanner) FromData(ctx context.Context, verify bool, data []byte) (results []detectors.Result, err error) { + dataStr := string(data) + + keyMatches := keyPat.FindAllStringSubmatch(dataStr, -1) + domainMatches := domainPat.FindAllStringSubmatch(dataStr, -1) + + for _, match := range keyMatches { + if len(match) != 2 { + continue + } + key := strings.TrimSpace(match[1]) + + for _, domainMatch := range domainMatches { + if len(domainMatch) != 2 { + continue + } + + domainRes := strings.TrimSpace(domainMatch[1]) + + s1 := detectors.Result{ + DetectorType: detectorspb.DetectorType_Loggly, + Raw: []byte(key), + RawV2: []byte(fmt.Sprintf("%s:%s", domainRes, key)), + + } + + if verify { + client := s.client + if client == nil { + client = defaultClient + } + req, err := http.NewRequestWithContext(ctx, "GET", "https://"+domainRes+"/apiv2/customer", nil) + if err != nil { + continue + } + req.Header.Add("Authorization", fmt.Sprintf("Bearer %s", key)) + res, err := client.Do(req) + if err == nil { + defer res.Body.Close() + if res.StatusCode >= 200 && res.StatusCode < 300 { + s1.Verified = true + } else if res.StatusCode == 401 { + // The secret is determinately not verified (nothing to do) + } else { + s1.VerificationError = fmt.Errorf("unexpected HTTP response status %d", res.StatusCode) + } + } else { + s1.VerificationError = err + } + } + + // This function will check false positives for common test words, but also it will make sure the key appears 'random' enough to be a real key. + if !s1.Verified && detectors.IsKnownFalsePositive(key, detectors.DefaultFalsePositives, true) { + continue + } + + results = append(results, s1) + } + } + + return results, nil +} + +func (s Scanner) Type() detectorspb.DetectorType { + return detectorspb.DetectorType_Loggly +} diff --git a/pkg/detectors/loggly/loggly_test.go b/pkg/detectors/loggly/loggly_test.go new file mode 100644 index 000000000000..aa19774824ed --- /dev/null +++ b/pkg/detectors/loggly/loggly_test.go @@ -0,0 +1,162 @@ +//go:build detectors +// +build detectors + +package loggly + +import ( + "context" + "fmt" + "github.com/google/go-cmp/cmp" + "github.com/google/go-cmp/cmp/cmpopts" + "testing" + "time" + + "github.com/trufflesecurity/trufflehog/v3/pkg/detectors" + + "github.com/trufflesecurity/trufflehog/v3/pkg/common" + "github.com/trufflesecurity/trufflehog/v3/pkg/pb/detectorspb" +) + +func TestLoggly_FromChunk(t *testing.T) { + ctx, cancel := context.WithTimeout(context.Background(), time.Second*5) + defer cancel() + testSecrets, err := common.GetSecret(ctx, "trufflehog-testing", "detectors4") + if err != nil { + t.Fatalf("could not get test secrets from GCP: %s", err) + } + secret := testSecrets.MustGetField("LOGGLY") + inactiveSecret := testSecrets.MustGetField("LOGGLY_INACTIVE") + domain := testSecrets.MustGetField("LOGGLY_DOMAIN") + + type args struct { + ctx context.Context + data []byte + verify bool + } + tests := []struct { + name string + s Scanner + args args + want []detectors.Result + wantErr bool + wantVerificationErr bool + }{ + { + name: "found, verified", + s: Scanner{}, + args: args{ + ctx: context.Background(), + data: []byte(fmt.Sprintf("You can find a loggly secret %s within loggly Domain %s", secret, domain)), + verify: true, + }, + want: []detectors.Result{ + { + DetectorType: detectorspb.DetectorType_Loggly, + Verified: true, + }, + }, + wantErr: false, + wantVerificationErr: false, + }, + { + name: "found, unverified", + s: Scanner{}, + args: args{ + ctx: context.Background(), + data: []byte(fmt.Sprintf("You can find a loggly secret %s within loggly Domain %s but not valid", inactiveSecret, domain)), // the secret would satisfy the regex but not pass validation + verify: true, + }, + want: []detectors.Result{ + { + DetectorType: detectorspb.DetectorType_Loggly, + Verified: false, + }, + }, + wantErr: false, + wantVerificationErr: false, + }, + { + name: "not found", + s: Scanner{}, + args: args{ + ctx: context.Background(), + data: []byte("You cannot find the secret within"), + verify: true, + }, + want: nil, + wantErr: false, + wantVerificationErr: false, + }, + { + name: "found, would be verified if not for timeout", + s: Scanner{client: common.SaneHttpClientTimeOut(1 * time.Microsecond)}, + args: args{ + ctx: context.Background(), + data: []byte(fmt.Sprintf("You can find a loggly secret %s within %s", secret, domain)), + verify: true, + }, + want: []detectors.Result{ + { + DetectorType: detectorspb.DetectorType_Loggly, + Verified: false, + }, + }, + wantErr: false, + wantVerificationErr: true, + }, + { + name: "found, verified but unexpected api surface", + s: Scanner{client: common.ConstantResponseHttpClient(404, "")}, + args: args{ + ctx: context.Background(), + data: []byte(fmt.Sprintf("You can find a loggly secret %s within %s", secret, domain)), + verify: true, + }, + want: []detectors.Result{ + { + DetectorType: detectorspb.DetectorType_Loggly, + Verified: false, + }, + }, + wantErr: false, + wantVerificationErr: true, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got, err := tt.s.FromData(tt.args.ctx, tt.args.verify, tt.args.data) + if (err != nil) != tt.wantErr { + t.Errorf("Loggly.FromData() error = %v, wantErr %v", err, tt.wantErr) + return + } + for i := range got { + if len(got[i].Raw) == 0 { + t.Fatalf("no raw secret present: \n %+v", got[i]) + } + if (got[i].VerificationError != nil) != tt.wantVerificationErr { + t.Fatalf("wantVerificationError = %v, verification error = %v", tt.wantVerificationErr, got[i].VerificationError) + } + } + ignoreOpts := cmpopts.IgnoreFields(detectors.Result{}, "Raw", "RawV2", "VerificationError") + if diff := cmp.Diff(got, tt.want, ignoreOpts); diff != "" { + t.Errorf("Loggly.FromData() %s diff: (-got +want)\n%s", tt.name, diff) + } + }) + } +} + +func BenchmarkFromData(benchmark *testing.B) { + ctx := context.Background() + s := Scanner{} + for name, data := range detectors.MustGetBenchmarkData() { + benchmark.Run(name, func(b *testing.B) { + b.ResetTimer() + for n := 0; n < b.N; n++ { + _, err := s.FromData(ctx, false, data) + if err != nil { + b.Fatal(err) + } + } + }) + } +} diff --git a/pkg/detectors/meaningcloud/meaningcloud.go b/pkg/detectors/meaningcloud/meaningcloud.go index b78691fb8710..ca1814de5dc3 100644 --- a/pkg/detectors/meaningcloud/meaningcloud.go +++ b/pkg/detectors/meaningcloud/meaningcloud.go @@ -3,6 +3,7 @@ package meaningcloud import ( "bytes" "context" + "encoding/json" "io" "mime/multipart" "net/http" @@ -32,6 +33,10 @@ func (s Scanner) Keywords() []string { return []string{"meaningcloud"} } +type response struct { + DeepTime float64 `json:"deepTime"` +} + // FromData will find and optionally verify MeaningCloud secrets in a given set of bytes. func (s Scanner) FromData(ctx context.Context, verify bool, data []byte) (results []detectors.Result, err error) { dataStr := string(data) @@ -78,7 +83,14 @@ func (s Scanner) FromData(ctx context.Context, verify bool, data []byte) (result if err == nil { defer res.Body.Close() if res.StatusCode >= 200 && res.StatusCode < 300 { - s1.Verified = true + var r response + if err := json.NewDecoder(res.Body).Decode(&r); err != nil { + s1.VerificationError = err + continue + } + if r.DeepTime > 0 { + s1.Verified = true + } } else { // This function will check false positives for common test words, but also it will make sure the key appears 'random' enough to be a real key. if detectors.IsKnownFalsePositive(resMatch, detectors.DefaultFalsePositives, true) { diff --git a/pkg/detectors/monday/monday.go b/pkg/detectors/monday/monday.go index 0a7400254f4e..9848e2bae51e 100644 --- a/pkg/detectors/monday/monday.go +++ b/pkg/detectors/monday/monday.go @@ -20,7 +20,7 @@ var ( client = common.SaneHttpClient() // Make sure that your group is surrounded in boundary characters such as below to reduce false positives. - keyPat = regexp.MustCompile(detectors.PrefixRegex([]string{"monday"}) + `\b(ey[a-zA-Z0-9_.]{210,225})\b`) + keyPat = regexp.MustCompile(detectors.PrefixRegex([]string{"monday"}) + `\b(eyJ[A-Za-z0-9-_]{15,100}\.eyJ[A-Za-z0-9-_]{100,300}\.[A-Za-z0-9-_]{25,100})\b`) ) // Keywords are used for efficiently pre-filtering chunks. diff --git a/pkg/detectors/monday/monday_test.go b/pkg/detectors/monday/monday_test.go index 5fc96e035dd8..659c980d5dca 100644 --- a/pkg/detectors/monday/monday_test.go +++ b/pkg/detectors/monday/monday_test.go @@ -19,7 +19,7 @@ import ( func TestMonday_FromChunk(t *testing.T) { ctx, cancel := context.WithTimeout(context.Background(), time.Second*5) defer cancel() - testSecrets, err := common.GetSecret(ctx, "trufflehog-testing", "detectors3") + testSecrets, err := common.GetSecret(ctx, "trufflehog-testing", "detectors5") if err != nil { t.Fatalf("could not get test secrets from GCP: %s", err) } diff --git a/pkg/detectors/newrelicpersonalapikey/newrelicpersonalapikey.go b/pkg/detectors/newrelicpersonalapikey/newrelicpersonalapikey.go index 456afd7d834b..2f954faa621c 100644 --- a/pkg/detectors/newrelicpersonalapikey/newrelicpersonalapikey.go +++ b/pkg/detectors/newrelicpersonalapikey/newrelicpersonalapikey.go @@ -48,11 +48,16 @@ func (s Scanner) FromData(ctx context.Context, verify bool, data []byte) (result if verify { req, err := http.NewRequestWithContext(ctx, "GET", "https://api.newrelic.com/v2/users.json", nil) - if err != nil { + reqEU, errEU := http.NewRequestWithContext(ctx, "GET", "https://api.eu.newrelic.com/v2/users.json", nil) + if err != nil || errEU != nil { continue } req.Header.Add("X-Api-Key", resMatch) + reqEU.Header.Add("X-Api-Key", resMatch) + res, err := client.Do(req) + resEU, errEU := client.Do(reqEU) + if err == nil { defer res.Body.Close() if res.StatusCode >= 200 && res.StatusCode < 300 { @@ -63,6 +68,16 @@ func (s Scanner) FromData(ctx context.Context, verify bool, data []byte) (result continue } } + } else if errEU == nil { + defer resEU.Body.Close() + if resEU.StatusCode >= 200 && resEU.StatusCode < 300 { + s1.Verified = true + } else { + // This function will check false positives for common test words, but also it will make sure the key appears 'random' enough to be a real key. + if detectors.IsKnownFalsePositive(resMatch, detectors.DefaultFalsePositives, false) { + continue + } + } } } diff --git a/pkg/detectors/openvpn/openvpn.go b/pkg/detectors/openvpn/openvpn.go new file mode 100644 index 000000000000..7a16304b21d4 --- /dev/null +++ b/pkg/detectors/openvpn/openvpn.go @@ -0,0 +1,109 @@ +package openvpn + +import ( + "context" + b64 "encoding/base64" + "fmt" + "net/http" + "regexp" + "strings" + + "github.com/trufflesecurity/trufflehog/v3/pkg/common" + "github.com/trufflesecurity/trufflehog/v3/pkg/detectors" + "github.com/trufflesecurity/trufflehog/v3/pkg/pb/detectorspb" +) + +type Scanner struct { + client *http.Client +} + +// Ensure the Scanner satisfies the interface at compile time. +var _ detectors.Detector = (*Scanner)(nil) + +var ( + defaultClient = common.SaneHttpClient() + + clientIDPat = regexp.MustCompile(detectors.PrefixRegex([]string{"openvpn"}) + `\b([A-Za-z0-9-]{3,40}\.[A-Za-z0-9-]{3,40})\b`) + clientSecretPat = regexp.MustCompile(`\b([a-zA-Z0-9_-]{64,})\b`) + domainPat = regexp.MustCompile(`\b(https?://[A-Za-z0-9-]+\.api\.openvpn\.com)\b`) + +) + +// Keywords are used for efficiently pre-filtering chunks. +// Use identifiers in the secret preferably, or the provider name. +func (s Scanner) Keywords() []string { + return []string{"openvpn"} +} + +// FromData will find and optionally verify Openvpn secrets in a given set of bytes. +func (s Scanner) FromData(ctx context.Context, verify bool, data []byte) (results []detectors.Result, err error) { + dataStr := string(data) + + domainMatches := domainPat.FindAllStringSubmatch(dataStr, -1) + clientIdMatches := clientIDPat.FindAllStringSubmatch(dataStr, -1) + clientSecretMatches := clientSecretPat.FindAllStringSubmatch(dataStr, -1) + + for _, clientIdMatch := range clientIdMatches { + clientIDRes := strings.TrimSpace(clientIdMatch[1]) + for _, clientSecretMatch := range clientSecretMatches { + clientSecretRes := strings.TrimSpace(clientSecretMatch[1]) + for _, domainMatch := range domainMatches { + domainRes := strings.TrimSpace(domainMatch[1]) + + s1 := detectors.Result{ + DetectorType: detectorspb.DetectorType_OpenVpn, + Raw: []byte(clientSecretRes), + RawV2: []byte(clientIDRes + clientSecretRes), + } + + if verify { + client := s.client + if client == nil { + client = defaultClient + } + + payload := strings.NewReader("grant_type=client_credentials") + // OpenVPN API is in beta, We'll have to update the API endpoint once + // Docs: https://openvpn.net/cloud-docs/developer/creating-api-credentials.html + req, err := http.NewRequestWithContext(ctx, "POST", domainRes + "/api/beta/oauth/token", payload) + if err != nil { + continue + } + + data := fmt.Sprintf("%s:%s", clientIDRes, clientSecretRes) + sEnc := b64.StdEncoding.EncodeToString([]byte(data)) + + req.Header.Add("Authorization", fmt.Sprintf("Basic %s", sEnc)) + req.Header.Add("content-type", "application/x-www-form-urlencoded") + res, err := client.Do(req) + if err == nil { + defer res.Body.Close() + if res.StatusCode >= 200 && res.StatusCode < 300 { + s1.Verified = true + } else if res.StatusCode == 401 { + // The secret is determinately not verified (nothing to do) + } else { + s1.VerificationError = fmt.Errorf("unexpected HTTP response status %d", res.StatusCode) + } + } else { + s1.VerificationError = err + } + } + // This function will check false positives for common test words, but also it will make sure the key appears 'random' enough to be a real key. + if detectors.IsKnownFalsePositive(clientSecretRes, detectors.DefaultFalsePositives, true) { + continue + } + results = append(results, s1) + } + } + + + + } + + return results, nil +} + +func (s Scanner) Type() detectorspb.DetectorType { + return detectorspb.DetectorType_OpenVpn +} diff --git a/pkg/detectors/openvpn/openvpn_test.go b/pkg/detectors/openvpn/openvpn_test.go new file mode 100644 index 000000000000..03a3547bba4f --- /dev/null +++ b/pkg/detectors/openvpn/openvpn_test.go @@ -0,0 +1,133 @@ +//go:build detectors +// +build detectors + +package openvpn + +import ( + "context" + "fmt" + "testing" + "time" + + "github.com/google/go-cmp/cmp" + "github.com/google/go-cmp/cmp/cmpopts" + + "github.com/trufflesecurity/trufflehog/v3/pkg/detectors" + + "github.com/trufflesecurity/trufflehog/v3/pkg/common" + "github.com/trufflesecurity/trufflehog/v3/pkg/pb/detectorspb" +) + +func TestOpenvpn_FromChunk(t *testing.T) { + ctx, cancel := context.WithTimeout(context.Background(), time.Second*5) + defer cancel() + testSecrets, err := common.GetSecret(ctx, "trufflehog-testing", "detectors5") + if err != nil { + t.Fatalf("could not get test secrets from GCP: %s", err) + } + + domain := testSecrets.MustGetField("OPENVPN_DOMAIN") + clientId := testSecrets.MustGetField("OPENVPN_CLIENT_ID") + clientSecret := testSecrets.MustGetField("OPENVPN_CLIENT_SECRET") + inactiveClientSecret := testSecrets.MustGetField("OPENVPN_CLIENT_SECRET_INACTIVE") + + type args struct { + ctx context.Context + data []byte + verify bool + } + tests := []struct { + name string + s Scanner + args args + want []detectors.Result + wantErr bool + wantVerificationErr bool + }{ + { + name: "found, verified", + s: Scanner{}, + args: args{ + ctx: context.Background(), + data: []byte(fmt.Sprintf("You can find a openvpn secret %s openvpn clientId %s and domain %s within", clientSecret, clientId, domain)), + verify: true, + }, + want: []detectors.Result{ + { + DetectorType: detectorspb.DetectorType_OpenVpn, + Verified: true, + RawV2: []byte(clientId + clientSecret), + }, + }, + wantErr: false, + wantVerificationErr: false, + }, + { + name: "found, unverified", + s: Scanner{}, + args: args{ + ctx: context.Background(), + data: []byte(fmt.Sprintf("You can find a openvpn secret %s openvpn clientId %s and domain %s within but not valid", inactiveClientSecret, clientId, domain)), // the secret would satisfy the regex but not pass validation + verify: true, + }, + want: []detectors.Result{ + { + DetectorType: detectorspb.DetectorType_OpenVpn, + Verified: false, + RawV2: []byte(clientId + inactiveClientSecret), + }, + }, + wantErr: false, + wantVerificationErr: false, + }, + { + name: "not found", + s: Scanner{}, + args: args{ + ctx: context.Background(), + data: []byte("You cannot find the secret within"), + verify: true, + }, + want: nil, + wantErr: false, + wantVerificationErr: false, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got, err := tt.s.FromData(tt.args.ctx, tt.args.verify, tt.args.data) + if (err != nil) != tt.wantErr { + t.Errorf("Openvpn.FromData() error = %v, wantErr %v", err, tt.wantErr) + return + } + for i := range got { + if len(got[i].Raw) == 0 { + t.Fatalf("no raw secret present: \n %+v", got[i]) + } + if (got[i].VerificationError != nil) != tt.wantVerificationErr { + t.Fatalf("wantVerificationError = %v, verification error = %v", tt.wantVerificationErr, got[i].VerificationError) + } + } + ignoreOpts := cmpopts.IgnoreFields(detectors.Result{}, "Raw", "VerificationError") + if diff := cmp.Diff(got, tt.want, ignoreOpts); diff != "" { + t.Errorf("Openvpn.FromData() %s diff: (-got +want)\n%s", tt.name, diff) + } + }) + } +} + +func BenchmarkFromData(benchmark *testing.B) { + ctx := context.Background() + s := Scanner{} + for name, data := range detectors.MustGetBenchmarkData() { + benchmark.Run(name, func(b *testing.B) { + b.ResetTimer() + for n := 0; n < b.N; n++ { + _, err := s.FromData(ctx, false, data) + if err != nil { + b.Fatal(err) + } + } + }) + } +} diff --git a/pkg/detectors/portainer/portainer.go b/pkg/detectors/portainer/portainer.go new file mode 100644 index 000000000000..433f90336c96 --- /dev/null +++ b/pkg/detectors/portainer/portainer.go @@ -0,0 +1,98 @@ +package portainer + +import ( + "context" + "fmt" + "net/http" + "regexp" + "strings" + + "github.com/trufflesecurity/trufflehog/v3/pkg/common" + "github.com/trufflesecurity/trufflehog/v3/pkg/detectors" + "github.com/trufflesecurity/trufflehog/v3/pkg/pb/detectorspb" +) + +type Scanner struct { + client *http.Client +} + +// Ensure the Scanner satisfies the interface at compile time. +var _ detectors.Detector = (*Scanner)(nil) + +var ( + defaultClient = common.SaneHttpClient() + // Make sure that your group is surrounded in boundary characters such as below to reduce false positives. + endpointPat = regexp.MustCompile(detectors.PrefixRegex([]string{"portainer"}) + `\b(https?:\/\/\S+(:[0-9]{4,5})?)\b`) + tokenPat = regexp.MustCompile(detectors.PrefixRegex([]string{"portainer"}) + `\b(eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9\.[0-9A-Za-z]{50,310}\.[0-9A-Z-a-z\-_]{43})\b`) +) + +// Keywords are used for efficiently pre-filtering chunks. +// Use identifiers in the secret preferably, or the provider name. +func (s Scanner) Keywords() []string { + return []string{"portainer"} +} + +// FromData will find and optionally verify Portainer secrets in a given set of bytes. +func (s Scanner) FromData(ctx context.Context, verify bool, data []byte) (results []detectors.Result, err error) { + dataStr := string(data) + + matches := tokenPat.FindAllStringSubmatch(dataStr, -1) + endpointMatches := endpointPat.FindAllStringSubmatch(dataStr, -1) + + for _, match := range matches { + if len(match) != 2 { + continue + } + resMatch := strings.TrimSpace(match[1]) + + for _, endpointMatch := range endpointMatches { + resEndpointMatch := strings.TrimSpace(endpointMatch[1]) + + s1 := detectors.Result{ + DetectorType: detectorspb.DetectorType_Portainer, + Raw: []byte(resMatch), + RawV2: []byte(resMatch + resEndpointMatch), + } + + if verify { + client := s.client + if client == nil { + client = defaultClient + } + req, err := http.NewRequestWithContext(ctx, "GET", resEndpointMatch + "/api/endpoints", nil) + if err != nil { + continue + } + req.Header.Add("Authorization", fmt.Sprintf("Bearer %s", resMatch)) + res, err := client.Do(req) + if err == nil { + defer res.Body.Close() + if res.StatusCode >= 200 && res.StatusCode < 300 { + s1.Verified = true + } else if res.StatusCode == 401 || res.StatusCode == 403 { + // The secret is determinately not verified (nothing to do) + } else { + s1.VerificationError = fmt.Errorf("unexpected HTTP response status %d", res.StatusCode) + } + } else { + s1.VerificationError = err + } + } + + if !s1.Verified && detectors.IsKnownFalsePositive(resMatch, detectors.DefaultFalsePositives, true) { + continue + } + + if len(endpointMatches) > 0 { + results = append(results, s1) + } + + } + } + + return results, nil +} + +func (s Scanner) Type() detectorspb.DetectorType { + return detectorspb.DetectorType_Portainer +} diff --git a/pkg/detectors/baseapiio/baseapiio_test.go b/pkg/detectors/portainer/portainer_test.go similarity index 50% rename from pkg/detectors/baseapiio/baseapiio_test.go rename to pkg/detectors/portainer/portainer_test.go index a09b7cc04695..4ce1ec49e348 100644 --- a/pkg/detectors/baseapiio/baseapiio_test.go +++ b/pkg/detectors/portainer/portainer_test.go @@ -1,7 +1,7 @@ //go:build detectors // +build detectors -package baseapiio +package portainer import ( "context" @@ -9,22 +9,25 @@ import ( "testing" "time" - "github.com/kylelemons/godebug/pretty" + "github.com/google/go-cmp/cmp" + "github.com/google/go-cmp/cmp/cmpopts" + "github.com/trufflesecurity/trufflehog/v3/pkg/detectors" "github.com/trufflesecurity/trufflehog/v3/pkg/common" "github.com/trufflesecurity/trufflehog/v3/pkg/pb/detectorspb" ) -func TestBaseApiIO_FromChunk(t *testing.T) { +func TestPortainer_FromChunk(t *testing.T) { ctx, cancel := context.WithTimeout(context.Background(), time.Second*5) defer cancel() - testSecrets, err := common.GetSecret(ctx, "trufflehog-testing", "detectors2") + testSecrets, err := common.GetSecret(ctx, "trufflehog-testing", "detectors5") if err != nil { t.Fatalf("could not get test secrets from GCP: %s", err) } - secret := testSecrets.MustGetField("BASEAPIIO") - inactiveSecret := testSecrets.MustGetField("BASEAPIIO_INACTIVE") + secret := testSecrets.MustGetField("PORTAINER") + endpoint := testSecrets.MustGetField("PORTAINER_ENDPOINT") + inactiveSecret := testSecrets.MustGetField("PORTAINER_INACTIVE") type args struct { ctx context.Context @@ -32,43 +35,48 @@ func TestBaseApiIO_FromChunk(t *testing.T) { verify bool } tests := []struct { - name string - s Scanner - args args - want []detectors.Result - wantErr bool + name string + s Scanner + args args + want []detectors.Result + wantErr bool + wantVerificationErr bool }{ { name: "found, verified", s: Scanner{}, args: args{ ctx: context.Background(), - data: []byte(fmt.Sprintf("You can find a baseapiio secret %s within", secret)), + data: []byte(fmt.Sprintf("You can find a portainer secret %s for portainer url %s", secret, endpoint)), verify: true, }, want: []detectors.Result{ { - DetectorType: detectorspb.DetectorType_BaseApiIO, + DetectorType: detectorspb.DetectorType_Portainer, Verified: true, + RawV2: []byte(secret + endpoint), }, }, - wantErr: false, + wantErr: false, + wantVerificationErr: false, }, { name: "found, unverified", s: Scanner{}, args: args{ ctx: context.Background(), - data: []byte(fmt.Sprintf("You can find a baseapiio secret %s within but not valid", inactiveSecret)), // the secret would satisfy the regex but not pass validation + data: []byte(fmt.Sprintf("You can find a portainer secret %s for portainer %s within but not valid", inactiveSecret, endpoint)), // the secret would satisfy the regex but not pass validation verify: true, }, want: []detectors.Result{ { - DetectorType: detectorspb.DetectorType_BaseApiIO, + DetectorType: detectorspb.DetectorType_Portainer, Verified: false, + RawV2: []byte(inactiveSecret + endpoint), }, }, - wantErr: false, + wantErr: false, + wantVerificationErr: false, }, { name: "not found", @@ -78,26 +86,29 @@ func TestBaseApiIO_FromChunk(t *testing.T) { data: []byte("You cannot find the secret within"), verify: true, }, - want: nil, - wantErr: false, + want: nil, + wantErr: false, + wantVerificationErr: false, }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - s := Scanner{} - got, err := s.FromData(tt.args.ctx, tt.args.verify, tt.args.data) + got, err := tt.s.FromData(tt.args.ctx, tt.args.verify, tt.args.data) if (err != nil) != tt.wantErr { - t.Errorf("BaseApiIO.FromData() error = %v, wantErr %v", err, tt.wantErr) + t.Errorf("Portainer.FromData() error = %v, wantErr %v", err, tt.wantErr) return } for i := range got { if len(got[i].Raw) == 0 { t.Fatalf("no raw secret present: \n %+v", got[i]) } - got[i].Raw = nil + if (got[i].VerificationError != nil) != tt.wantVerificationErr { + t.Fatalf("wantVerificationError = %v, verification error = %v", tt.wantVerificationErr, got[i].VerificationError) + } } - if diff := pretty.Compare(got, tt.want); diff != "" { - t.Errorf("BaseApiIO.FromData() %s diff: (-got +want)\n%s", tt.name, diff) + ignoreOpts := cmpopts.IgnoreFields(detectors.Result{}, "Raw", "VerificationError") + if diff := cmp.Diff(got, tt.want, ignoreOpts); diff != "" { + t.Errorf("Portainer.FromData() %s diff: (-got +want)\n%s", tt.name, diff) } }) } diff --git a/pkg/detectors/portainertoken/portainertoken.go b/pkg/detectors/portainertoken/portainertoken.go new file mode 100644 index 000000000000..9417b5a0db03 --- /dev/null +++ b/pkg/detectors/portainertoken/portainertoken.go @@ -0,0 +1,99 @@ +package portainertoken + +import ( + "context" + "fmt" + "net/http" + "regexp" + "strings" + + "github.com/trufflesecurity/trufflehog/v3/pkg/common" + "github.com/trufflesecurity/trufflehog/v3/pkg/detectors" + "github.com/trufflesecurity/trufflehog/v3/pkg/pb/detectorspb" +) + +type Scanner struct { + client *http.Client +} + +// Ensure the Scanner satisfies the interface at compile time. +var _ detectors.Detector = (*Scanner)(nil) + +var ( + defaultClient = common.SaneHttpClient() + // Make sure that your group is surrounded in boundary characters such as below to reduce false positives. + keyPat = regexp.MustCompile(detectors.PrefixRegex([]string{"portainertoken"}) + `\b(ptr_[A-Za-z0-9\/_\-+=]{20,60})`) + endpointPat = regexp.MustCompile(detectors.PrefixRegex([]string{"portainer"}) + `\b(https?:\/\/\S+(:[0-9]{4,5})?)\b`) +) + +// Keywords are used for efficiently pre-filtering chunks. +// Use identifiers in the secret preferably, or the provider name. +func (s Scanner) Keywords() []string { + return []string{"portainertoken"} +} + +// FromData will find and optionally verify Portainertoken secrets in a given set of bytes. +func (s Scanner) FromData(ctx context.Context, verify bool, data []byte) (results []detectors.Result, err error) { + dataStr := string(data) + + matches := keyPat.FindAllStringSubmatch(dataStr, -1) + endpointMatches := endpointPat.FindAllStringSubmatch(dataStr, -1) + + for _, match := range matches { + if len(match) != 2 { + continue + } + resMatch := strings.TrimSpace(match[1]) + + for _, endpointMatch := range endpointMatches { + resEndpointMatch := strings.TrimSpace(endpointMatch[1]) + + s1 := detectors.Result{ + DetectorType: detectorspb.DetectorType_PortainerToken, + Raw: []byte(resMatch), + RawV2: []byte(resMatch + resEndpointMatch), + } + + if verify { + client := s.client + if client == nil { + client = defaultClient + } + req, err := http.NewRequestWithContext(ctx, "GET", resEndpointMatch + "/api/stacks", nil) + if err != nil { + continue + } + + req.Header.Add("X-API-Key", resMatch) + + res, err := client.Do(req) + + if err == nil { + defer res.Body.Close() + if res.StatusCode >= 200 && res.StatusCode < 300 { + s1.Verified = true + } else if res.StatusCode == 401 { + // The secret is determinately not verified (nothing to do) + } else { + s1.VerificationError = fmt.Errorf("unexpected HTTP response status %d", res.StatusCode) + } + } else { + s1.VerificationError = err + } + } + + if !s1.Verified && detectors.IsKnownFalsePositive(resMatch, detectors.DefaultFalsePositives, true) { + continue + } + + if len(endpointMatches) > 0 { + results = append(results, s1) + } + } + } + return results, nil +} + +func (s Scanner) Type() detectorspb.DetectorType { + return detectorspb.DetectorType_PortainerToken +} diff --git a/pkg/detectors/portainertoken/portainertoken_test.go b/pkg/detectors/portainertoken/portainertoken_test.go new file mode 100644 index 000000000000..2f8a61d8b3f4 --- /dev/null +++ b/pkg/detectors/portainertoken/portainertoken_test.go @@ -0,0 +1,131 @@ +//go:build detectors +// +build detectors + +package portainertoken + +import ( + "context" + "fmt" + "testing" + "time" + + "github.com/google/go-cmp/cmp" + "github.com/google/go-cmp/cmp/cmpopts" + + "github.com/trufflesecurity/trufflehog/v3/pkg/detectors" + + "github.com/trufflesecurity/trufflehog/v3/pkg/common" + "github.com/trufflesecurity/trufflehog/v3/pkg/pb/detectorspb" +) + +func TestPortainertoken_FromChunk(t *testing.T) { + ctx, cancel := context.WithTimeout(context.Background(), time.Second*5) + defer cancel() + testSecrets, err := common.GetSecret(ctx, "trufflehog-testing", "detectors5") + if err != nil { + t.Fatalf("could not get test secrets from GCP: %s", err) + } + secret := testSecrets.MustGetField("PORTAINERTOKEN") + inactiveSecret := testSecrets.MustGetField("PORTAINERTOKEN_INACTIVE") + endpoint := testSecrets.MustGetField("PORTAINER_ENDPOINT") + + type args struct { + ctx context.Context + data []byte + verify bool + } + tests := []struct { + name string + s Scanner + args args + want []detectors.Result + wantErr bool + wantVerificationErr bool + }{ + { + name: "found, verified", + s: Scanner{}, + args: args{ + ctx: context.Background(), + data: []byte(fmt.Sprintf("You can find a portainertoken secret %s within for portainer url %s", secret, endpoint)), + verify: true, + }, + want: []detectors.Result{ + { + DetectorType: detectorspb.DetectorType_PortainerToken, + Verified: true, + RawV2: []byte(secret + endpoint), + }, + }, + wantErr: false, + wantVerificationErr: false, + }, + { + name: "found, unverified", + s: Scanner{}, + args: args{ + ctx: context.Background(), + data: []byte(fmt.Sprintf("You can find a portainertoken secret %s within but not valid for portainer url %s", inactiveSecret, endpoint)), // the secret would satisfy the regex but not pass validation + verify: true, + }, + want: []detectors.Result{ + { + DetectorType: detectorspb.DetectorType_PortainerToken, + Verified: false, + RawV2: []byte(inactiveSecret + endpoint), + }, + }, + wantErr: false, + wantVerificationErr: false, + }, + { + name: "not found", + s: Scanner{}, + args: args{ + ctx: context.Background(), + data: []byte("You cannot find the secret within"), + verify: true, + }, + want: nil, + wantErr: false, + wantVerificationErr: false, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got, err := tt.s.FromData(tt.args.ctx, tt.args.verify, tt.args.data) + if (err != nil) != tt.wantErr { + t.Errorf("Portainertoken.FromData() error = %v, wantErr %v", err, tt.wantErr) + return + } + for i := range got { + if len(got[i].Raw) == 0 { + t.Fatalf("no raw secret present: \n %+v", got[i]) + } + if (got[i].VerificationError != nil) != tt.wantVerificationErr { + t.Fatalf("wantVerificationError = %v, verification error = %v", tt.wantVerificationErr, got[i].VerificationError) + } + } + ignoreOpts := cmpopts.IgnoreFields(detectors.Result{}, "Raw", "VerificationError") + if diff := cmp.Diff(got, tt.want, ignoreOpts); diff != "" { + t.Errorf("Portainertoken.FromData() %s diff: (-got +want)\n%s", tt.name, diff) + } + }) + } +} + +func BenchmarkFromData(benchmark *testing.B) { + ctx := context.Background() + s := Scanner{} + for name, data := range detectors.MustGetBenchmarkData() { + benchmark.Run(name, func(b *testing.B) { + b.ResetTimer() + for n := 0; n < b.N; n++ { + _, err := s.FromData(ctx, false, data) + if err != nil { + b.Fatal(err) + } + } + }) + } +} diff --git a/pkg/detectors/quickmetrics/quickmetrics.go b/pkg/detectors/quickmetrics/quickmetrics.go deleted file mode 100644 index e7aa8ae4c4a3..000000000000 --- a/pkg/detectors/quickmetrics/quickmetrics.go +++ /dev/null @@ -1,79 +0,0 @@ -package quickmetrics - -import ( - "context" - "net/http" - "regexp" - "strings" - - "github.com/trufflesecurity/trufflehog/v3/pkg/common" - "github.com/trufflesecurity/trufflehog/v3/pkg/detectors" - "github.com/trufflesecurity/trufflehog/v3/pkg/pb/detectorspb" -) - -type Scanner struct{} - -// Ensure the Scanner satisfies the interface at compile time. -var _ detectors.Detector = (*Scanner)(nil) - -var ( - client = common.SaneHttpClient() - - // Make sure that your group is surrounded in boundary characters such as below to reduce false positives. - keyPat = regexp.MustCompile(detectors.PrefixRegex([]string{"quickmetrics"}) + `\b([a-zA-Z0-9_-]{22})\b`) -) - -// Keywords are used for efficiently pre-filtering chunks. -// Use identifiers in the secret preferably, or the provider name. -func (s Scanner) Keywords() []string { - return []string{"quickmetrics"} -} - -// FromData will find and optionally verify QuickMetrics secrets in a given set of bytes. -func (s Scanner) FromData(ctx context.Context, verify bool, data []byte) (results []detectors.Result, err error) { - dataStr := string(data) - - matches := keyPat.FindAllStringSubmatch(dataStr, -1) - - for _, match := range matches { - if len(match) != 2 { - continue - } - resMatch := strings.TrimSpace(match[1]) - - s1 := detectors.Result{ - DetectorType: detectorspb.DetectorType_QuickMetrics, - Raw: []byte(resMatch), - } - - if verify { - payload := strings.NewReader(`[{"name":"api.response.time","dimension":null,"values":[[1568319841,12.4],[1568319856,9.3],[1568319860,234],[1568319863,3.2]]},{"name":"click.color","dimension":"green","values":[[1568319841,1],[1568319856,1],[1568319860,1],[1568319863,1]]}]`) - req, err := http.NewRequestWithContext(ctx, "POST", "https://qckm.io/list", payload) - if err != nil { - continue - } - req.Header.Add("Content-Type", "application/json") - req.Header.Add("x-qm-key", resMatch) - res, err := client.Do(req) - if err == nil { - defer res.Body.Close() - if res.StatusCode >= 200 && res.StatusCode < 300 { - s1.Verified = true - } else { - // This function will check false positives for common test words, but also it will make sure the key appears 'random' enough to be a real key. - if detectors.IsKnownFalsePositive(resMatch, detectors.DefaultFalsePositives, true) { - continue - } - } - } - } - - results = append(results, s1) - } - - return results, nil -} - -func (s Scanner) Type() detectorspb.DetectorType { - return detectorspb.DetectorType_QuickMetrics -} diff --git a/pkg/detectors/quickmetrics/quickmetrics_test.go b/pkg/detectors/quickmetrics/quickmetrics_test.go deleted file mode 100644 index f0973805f286..000000000000 --- a/pkg/detectors/quickmetrics/quickmetrics_test.go +++ /dev/null @@ -1,120 +0,0 @@ -//go:build detectors -// +build detectors - -package quickmetrics - -import ( - "context" - "fmt" - "testing" - "time" - - "github.com/kylelemons/godebug/pretty" - "github.com/trufflesecurity/trufflehog/v3/pkg/detectors" - - "github.com/trufflesecurity/trufflehog/v3/pkg/common" - "github.com/trufflesecurity/trufflehog/v3/pkg/pb/detectorspb" -) - -func TestQuickMetrics_FromChunk(t *testing.T) { - ctx, cancel := context.WithTimeout(context.Background(), time.Second*5) - defer cancel() - testSecrets, err := common.GetSecret(ctx, "trufflehog-testing", "detectors1") - if err != nil { - t.Fatalf("could not get test secrets from GCP: %s", err) - } - secret := testSecrets.MustGetField("QUICKMETRICS") - inactiveSecret := testSecrets.MustGetField("QUICKMETRICS_INACTIVE") - - type args struct { - ctx context.Context - data []byte - verify bool - } - tests := []struct { - name string - s Scanner - args args - want []detectors.Result - wantErr bool - }{ - { - name: "found, verified", - s: Scanner{}, - args: args{ - ctx: context.Background(), - data: []byte(fmt.Sprintf("You can find a quickmetrics secret %s within", secret)), - verify: true, - }, - want: []detectors.Result{ - { - DetectorType: detectorspb.DetectorType_QuickMetrics, - Verified: true, - }, - }, - wantErr: false, - }, - { - name: "found, unverified", - s: Scanner{}, - args: args{ - ctx: context.Background(), - data: []byte(fmt.Sprintf("You can find a quickmetrics secret %s within but not valid", inactiveSecret)), // the secret would satisfy the regex but not pass validation - verify: true, - }, - want: []detectors.Result{ - { - DetectorType: detectorspb.DetectorType_QuickMetrics, - Verified: false, - }, - }, - wantErr: false, - }, - { - name: "not found", - s: Scanner{}, - args: args{ - ctx: context.Background(), - data: []byte("You cannot find the secret within"), - verify: true, - }, - want: nil, - wantErr: false, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - s := Scanner{} - got, err := s.FromData(tt.args.ctx, tt.args.verify, tt.args.data) - if (err != nil) != tt.wantErr { - t.Errorf("QuickMetrics.FromData() error = %v, wantErr %v", err, tt.wantErr) - return - } - for i := range got { - if len(got[i].Raw) == 0 { - t.Fatalf("no raw secret present: \n %+v", got[i]) - } - got[i].Raw = nil - } - if diff := pretty.Compare(got, tt.want); diff != "" { - t.Errorf("QuickMetrics.FromData() %s diff: (-got +want)\n%s", tt.name, diff) - } - }) - } -} - -func BenchmarkFromData(benchmark *testing.B) { - ctx := context.Background() - s := Scanner{} - for name, data := range detectors.MustGetBenchmarkData() { - benchmark.Run(name, func(b *testing.B) { - b.ResetTimer() - for n := 0; n < b.N; n++ { - _, err := s.FromData(ctx, false, data) - if err != nil { - b.Fatal(err) - } - } - }) - } -} diff --git a/pkg/detectors/screenshotapi/screenshotapi.go b/pkg/detectors/screenshotapi/screenshotapi.go index ee36582a68b6..e2b453050f28 100644 --- a/pkg/detectors/screenshotapi/screenshotapi.go +++ b/pkg/detectors/screenshotapi/screenshotapi.go @@ -2,6 +2,7 @@ package screenshotapi import ( "context" + "encoding/json" "net/http" "regexp" "strings" @@ -30,6 +31,10 @@ func (s Scanner) Keywords() []string { return []string{"screenshotapi"} } +type response struct { + Screenshot string `json:"screenshot"` +} + // FromData will find and optionally verify ScreenshotAPI secrets in a given set of bytes. func (s Scanner) FromData(ctx context.Context, verify bool, data []byte) (results []detectors.Result, err error) { dataStr := string(data) @@ -50,14 +55,19 @@ func (s Scanner) FromData(ctx context.Context, verify bool, data []byte) (result if verify { timeout := 10 * time.Second client.Timeout = timeout - req, err := http.NewRequestWithContext(ctx, "GET", "https://shot.screenshotapi.net/screenshot?token="+resMatch+"&url=https://google.com&width=1920&height=1080&output=image", nil) + req, err := http.NewRequestWithContext(ctx, "GET", "https://shot.screenshotapi.net/screenshot?token="+resMatch+"&url=https://google.com&width=1920&height=1080", nil) if err != nil { continue } res, err := client.Do(req) if err == nil { defer res.Body.Close() - if res.StatusCode >= 200 && res.StatusCode < 300 { + var r response + if err := json.NewDecoder(res.Body).Decode(&r); err != nil { + s1.VerificationError = err + continue + } + if res.StatusCode >= 200 && res.StatusCode < 300 && r.Screenshot != "" { s1.Verified = true } else { // This function will check false positives for common test words, but also it will make sure the key appears 'random' enough to be a real key. diff --git a/pkg/detectors/supernotesapi/supernotesapi.go b/pkg/detectors/supernotesapi/supernotesapi.go index 2e3586fe1381..98b2c5eb04ca 100644 --- a/pkg/detectors/supernotesapi/supernotesapi.go +++ b/pkg/detectors/supernotesapi/supernotesapi.go @@ -47,7 +47,7 @@ func (s Scanner) FromData(ctx context.Context, verify bool, data []byte) (result } if verify { - req, err := http.NewRequestWithContext(ctx, "GET", "https://api.supernotes.app/v1/user/", nil) + req, err := http.NewRequestWithContext(ctx, "GET", "https://api.supernotes.app/v1/user", nil) if err != nil { continue } diff --git a/pkg/detectors/baseapiio/baseapiio.go b/pkg/detectors/vagrantcloudpersonaltoken/vagrantcloudpersonaltoken.go similarity index 54% rename from pkg/detectors/baseapiio/baseapiio.go rename to pkg/detectors/vagrantcloudpersonaltoken/vagrantcloudpersonaltoken.go index f534d493a221..c78dbde27f61 100644 --- a/pkg/detectors/baseapiio/baseapiio.go +++ b/pkg/detectors/vagrantcloudpersonaltoken/vagrantcloudpersonaltoken.go @@ -1,9 +1,8 @@ -package baseapiio +package vagrantcloudpersonaltoken import ( "context" "fmt" - "io" "net/http" "regexp" "strings" @@ -13,25 +12,26 @@ import ( "github.com/trufflesecurity/trufflehog/v3/pkg/pb/detectorspb" ) -type Scanner struct{} +type Scanner struct { + client *http.Client +} // Ensure the Scanner satisfies the interface at compile time. var _ detectors.Detector = (*Scanner)(nil) var ( - client = common.SaneHttpClient() - + defaultClient = common.SaneHttpClient() // Make sure that your group is surrounded in boundary characters such as below to reduce false positives. - keyPat = regexp.MustCompile(detectors.PrefixRegex([]string{"baseapi", "base-api"}) + `\b([0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12})\b`) + keyPat = regexp.MustCompile(detectors.PrefixRegex([]string{"vagrant"}) + `\b([A-Za-z0-9]{14}.atlasv1.[A-Za-z0-9]{67})\b`) ) // Keywords are used for efficiently pre-filtering chunks. // Use identifiers in the secret preferably, or the provider name. func (s Scanner) Keywords() []string { - return []string{"baseapi", "base-api"} + return []string{"vagrant"} } -// FromData will find and optionally verify BaseApiIO secrets in a given set of bytes. +// FromData will find and optionally verify Vagrantcloudpersonaltoken secrets in a given set of bytes. func (s Scanner) FromData(ctx context.Context, verify bool, data []byte) (results []detectors.Result, err error) { dataStr := string(data) @@ -44,12 +44,17 @@ func (s Scanner) FromData(ctx context.Context, verify bool, data []byte) (result resMatch := strings.TrimSpace(match[1]) s1 := detectors.Result{ - DetectorType: detectorspb.DetectorType_BaseApiIO, + DetectorType: detectorspb.DetectorType_VagrantCloudPersonalToken, Raw: []byte(resMatch), } if verify { - req, err := http.NewRequestWithContext(ctx, "GET", "https://api.base-api.io/v1/forms?page=1&per_page=10", nil) + client := s.client + if client == nil { + client = defaultClient + } + + req, err := http.NewRequestWithContext(ctx, "GET", "https://app.vagrantup.com/api/v2/authenticate", nil) if err != nil { continue } @@ -57,23 +62,23 @@ func (s Scanner) FromData(ctx context.Context, verify bool, data []byte) (result res, err := client.Do(req) if err == nil { defer res.Body.Close() - bodyBytes, err := io.ReadAll(res.Body) - if err != nil { - continue - } - body := string(bodyBytes) - - if strings.Contains(body, "items") { + if res.StatusCode >= 200 && res.StatusCode < 300 { s1.Verified = true + } else if res.StatusCode == 401 { + // The secret is determinately not verified (nothing to do) } else { - if detectors.IsKnownFalsePositive(resMatch, detectors.DefaultFalsePositives, true) { - continue - } + s1.VerificationError = fmt.Errorf("unexpected HTTP response status %d", res.StatusCode) } - + } else { + s1.VerificationError = err } } + // This function will check false positives for common test words, but also it will make sure the key appears 'random' enough to be a real key. + if !s1.Verified && detectors.IsKnownFalsePositive(resMatch, detectors.DefaultFalsePositives, true) { + continue + } + results = append(results, s1) } @@ -81,5 +86,5 @@ func (s Scanner) FromData(ctx context.Context, verify bool, data []byte) (result } func (s Scanner) Type() detectorspb.DetectorType { - return detectorspb.DetectorType_BaseApiIO + return detectorspb.DetectorType_VagrantCloudPersonalToken } diff --git a/pkg/detectors/datafire/datafire_test.go b/pkg/detectors/vagrantcloudpersonaltoken/vagrantcloudpersonaltoken_test.go similarity index 50% rename from pkg/detectors/datafire/datafire_test.go rename to pkg/detectors/vagrantcloudpersonaltoken/vagrantcloudpersonaltoken_test.go index 18c08092827b..12e10a637d1f 100644 --- a/pkg/detectors/datafire/datafire_test.go +++ b/pkg/detectors/vagrantcloudpersonaltoken/vagrantcloudpersonaltoken_test.go @@ -1,7 +1,7 @@ //go:build detectors // +build detectors -package datafire +package vagrantcloudpersonaltoken import ( "context" @@ -9,22 +9,24 @@ import ( "testing" "time" - "github.com/kylelemons/godebug/pretty" + "github.com/google/go-cmp/cmp" + "github.com/google/go-cmp/cmp/cmpopts" + "github.com/trufflesecurity/trufflehog/v3/pkg/detectors" "github.com/trufflesecurity/trufflehog/v3/pkg/common" "github.com/trufflesecurity/trufflehog/v3/pkg/pb/detectorspb" ) -func TestDataFire_FromChunk(t *testing.T) { +func TestVagrantcloudpersonaltoken_FromChunk(t *testing.T) { ctx, cancel := context.WithTimeout(context.Background(), time.Second*5) defer cancel() - testSecrets, err := common.GetSecret(ctx, "trufflehog-testing", "detectors1") + testSecrets, err := common.GetSecret(ctx, "trufflehog-testing", "detectors5") if err != nil { t.Fatalf("could not get test secrets from GCP: %s", err) } - secret := testSecrets.MustGetField("DATAFIRE") - inactiveSecret := testSecrets.MustGetField("DATAFIRE_INACTIVE") + secret := testSecrets.MustGetField("VAGRANTCLOUDPERSONALTOKEN") + inactiveSecret := testSecrets.MustGetField("VAGRANTCLOUDPERSONALTOKEN_INACTIVE") type args struct { ctx context.Context @@ -32,43 +34,46 @@ func TestDataFire_FromChunk(t *testing.T) { verify bool } tests := []struct { - name string - s Scanner - args args - want []detectors.Result - wantErr bool + name string + s Scanner + args args + want []detectors.Result + wantErr bool + wantVerificationErr bool }{ { name: "found, verified", s: Scanner{}, args: args{ ctx: context.Background(), - data: []byte(fmt.Sprintf("You can find a datafire secret %s within", secret)), + data: []byte(fmt.Sprintf("You can find a vagrantcloudpersonaltoken secret %s within", secret)), verify: true, }, want: []detectors.Result{ { - DetectorType: detectorspb.DetectorType_DataFire, + DetectorType: detectorspb.DetectorType_VagrantCloudPersonalToken, Verified: true, }, }, - wantErr: false, + wantErr: false, + wantVerificationErr: false, }, { name: "found, unverified", s: Scanner{}, args: args{ ctx: context.Background(), - data: []byte(fmt.Sprintf("You can find a datafire secret %s within but not valid", inactiveSecret)), // the secret would satisfy the regex but not pass validation + data: []byte(fmt.Sprintf("You can find a vagrantcloudpersonaltoken secret %s within but not valid", inactiveSecret)), // the secret would satisfy the regex but not pass validation verify: true, }, want: []detectors.Result{ { - DetectorType: detectorspb.DetectorType_DataFire, + DetectorType: detectorspb.DetectorType_VagrantCloudPersonalToken, Verified: false, }, }, - wantErr: false, + wantErr: false, + wantVerificationErr: false, }, { name: "not found", @@ -78,26 +83,29 @@ func TestDataFire_FromChunk(t *testing.T) { data: []byte("You cannot find the secret within"), verify: true, }, - want: nil, - wantErr: false, + want: nil, + wantErr: false, + wantVerificationErr: false, }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - s := Scanner{} - got, err := s.FromData(tt.args.ctx, tt.args.verify, tt.args.data) + got, err := tt.s.FromData(tt.args.ctx, tt.args.verify, tt.args.data) if (err != nil) != tt.wantErr { - t.Errorf("DataFire.FromData() error = %v, wantErr %v", err, tt.wantErr) + t.Errorf("Vagrantcloudpersonaltoken.FromData() error = %v, wantErr %v", err, tt.wantErr) return } for i := range got { if len(got[i].Raw) == 0 { t.Fatalf("no raw secret present: \n %+v", got[i]) } - got[i].Raw = nil + if (got[i].VerificationError != nil) != tt.wantVerificationErr { + t.Fatalf("wantVerificationError = %v, verification error = %v", tt.wantVerificationErr, got[i].VerificationError) + } } - if diff := pretty.Compare(got, tt.want); diff != "" { - t.Errorf("DataFire.FromData() %s diff: (-got +want)\n%s", tt.name, diff) + ignoreOpts := cmpopts.IgnoreFields(detectors.Result{}, "Raw", "VerificationError") + if diff := cmp.Diff(got, tt.want, ignoreOpts); diff != "" { + t.Errorf("Vagrantcloudpersonaltoken.FromData() %s diff: (-got +want)\n%s", tt.name, diff) } }) } diff --git a/pkg/engine/ahocorasickcore.go b/pkg/engine/ahocorasickcore.go new file mode 100644 index 000000000000..2e0fa5f8184d --- /dev/null +++ b/pkg/engine/ahocorasickcore.go @@ -0,0 +1,111 @@ +package engine + +import ( + "strings" + + ahocorasick "github.com/BobuSumisu/aho-corasick" + + "github.com/trufflesecurity/trufflehog/v3/pkg/context" + "github.com/trufflesecurity/trufflehog/v3/pkg/detectors" + "github.com/trufflesecurity/trufflehog/v3/pkg/pb/detectorspb" +) + +// detectorKey is used to identify a detector in the keywordsToDetectors map. +// Multiple detectors can have the same detector type but different versions. +// This allows us to identify a detector by its type and version. +type detectorKey struct { + detectorType detectorspb.DetectorType + version int +} + +// DetectorInfo is used to store a detector and whether it should be verified. +type DetectorInfo struct { + detectors.Detector + ShouldVerify bool +} + +// AhoCorasickCore encapsulates the operations and data structures used for keyword matching via the +// Aho-Corasick algorithm. It is responsible for constructing and managing the trie for efficient +// substring searches, as well as mapping keywords to their associated detectors for rapid lookups. +type AhoCorasickCore struct { + // prefilter is a ahocorasick struct used for doing efficient string + // matching given a set of words. (keywords from the rules in the config) + prefilter ahocorasick.Trie + // Maps for efficient lookups during detection. + detectorTypeToDetectorInfo map[detectorKey]DetectorInfo + detectors map[bool][]detectors.Detector + keywordsToDetectors map[string][]detectorKey +} + +// NewAhoCorasickCore allocates and initializes a new instance of AhoCorasickCore. +// It creates an empty keyword-to-detectors map for future string matching operations. +// The map detectorTypeToDetectorInfo is pre-allocated based on the size of detectors +// provided, for efficient storage and lookup of detector information. +func NewAhoCorasickCore(detectors map[bool][]detectors.Detector) *AhoCorasickCore { + return &AhoCorasickCore{ + keywordsToDetectors: make(map[string][]detectorKey), + detectors: detectors, + detectorTypeToDetectorInfo: make(map[detectorKey]DetectorInfo, len(detectors[true])+len(detectors[false])), + } +} + +// Setup initializes the internal state of AhoCorasickCore to prepare it for keyword matching. +// This involves pre-filtering setup and lookup optimization, critical for the engine's performance. +func (ac *AhoCorasickCore) Setup(ctx context.Context) { + // Prepare maps for fast detector lookups, instead of scanning through an array of detectors for every chunk. + var keywords []string + for verify, detectorsSet := range ac.detectors { + for _, d := range detectorsSet { + key := createDetectorKey(d) + ac.detectorTypeToDetectorInfo[key] = DetectorInfo{Detector: d, ShouldVerify: verify} + keywords = ac.extractAndMapKeywords(d, key, keywords) + } + } + + // Use the Ahocorasick algorithm to create a trie structure for efficient keyword matching. + // This ensures that we can rapidly match against a vast set of keywords without individually comparing each one. + ac.prefilter = *ahocorasick.NewTrieBuilder().AddStrings(keywords).Build() + ctx.Logger().V(4).Info("AhoCorasickCore Setup complete") +} + +// createDetectorKey creates a unique key for each detector. This key based on type and version, +// it ensures faster lookups and reduces redundancy in our main detector store. +func createDetectorKey(d detectors.Detector) detectorKey { + detectorType := d.Type() + var version int + if v, ok := d.(detectors.Versioner); ok { + version = v.Version() + } + return detectorKey{detectorType: detectorType, version: version} +} + +// extractAndMapKeywords captures keywords associated with each detector and maps them. +// This allows us to quickly determine which detectors are relevant based on the presence of certain keywords. +func (ac *AhoCorasickCore) extractAndMapKeywords(d detectors.Detector, key detectorKey, keywords []string) []string { + for _, kw := range d.Keywords() { + kwLower := strings.ToLower(kw) + keywords = append(keywords, kwLower) + ac.keywordsToDetectors[kwLower] = append(ac.keywordsToDetectors[kwLower], key) + } + return keywords +} + +// MatchString performs a string match using the Aho-Corasick algorithm, returning an array of matches. +// Designed for internal use within the AhoCorasickCore component. +func (ac *AhoCorasickCore) MatchString(input string) []*ahocorasick.Match { + return ac.prefilter.MatchString(strings.ToLower(input)) +} + +// PopulateDetectorsByMatch populates the given detectorMap based on the Aho-Corasick match results. +// This method is designed to reuse the same map for performance optimization, +// reducing the need for repeated allocations within each detector worker in the engine. +func (ac *AhoCorasickCore) PopulateDetectorsByMatch(match *ahocorasick.Match, detectors map[detectorspb.DetectorType]DetectorInfo) bool { + matchedKeys, ok := ac.keywordsToDetectors[match.MatchString()] + if !ok { + return false + } + for _, key := range matchedKeys { + detectors[key.detectorType] = ac.detectorTypeToDetectorInfo[key] + } + return true +} diff --git a/pkg/engine/defaults.go b/pkg/engine/defaults.go index 0fe710589faf..ae668d279b52 100644 --- a/pkg/engine/defaults.go +++ b/pkg/engine/defaults.go @@ -4,6 +4,8 @@ import ( "github.com/trufflesecurity/trufflehog/v3/pkg/detectors/anthropic" "github.com/trufflesecurity/trufflehog/v3/pkg/detectors/envoyapikey" "github.com/trufflesecurity/trufflehog/v3/pkg/detectors/huggingface" + "github.com/trufflesecurity/trufflehog/v3/pkg/detectors/ip2location" + "github.com/trufflesecurity/trufflehog/v3/pkg/detectors/openvpn" "github.com/trufflesecurity/trufflehog/v3/pkg/detectors/ramp" "github.com/trufflesecurity/trufflehog/v3/pkg/detectors/salesforce" "github.com/trufflesecurity/trufflehog/v3/pkg/detectors/snowflake" @@ -74,7 +76,6 @@ import ( "github.com/trufflesecurity/trufflehog/v3/pkg/detectors/azure" "github.com/trufflesecurity/trufflehog/v3/pkg/detectors/bannerbear" "github.com/trufflesecurity/trufflehog/v3/pkg/detectors/baremetrics" - "github.com/trufflesecurity/trufflehog/v3/pkg/detectors/baseapiio" "github.com/trufflesecurity/trufflehog/v3/pkg/detectors/beamer" "github.com/trufflesecurity/trufflehog/v3/pkg/detectors/beebole" "github.com/trufflesecurity/trufflehog/v3/pkg/detectors/besnappy" @@ -85,7 +86,6 @@ import ( "github.com/trufflesecurity/trufflehog/v3/pkg/detectors/bitfinex" "github.com/trufflesecurity/trufflehog/v3/pkg/detectors/bitlyaccesstoken" "github.com/trufflesecurity/trufflehog/v3/pkg/detectors/bitmex" - "github.com/trufflesecurity/trufflehog/v3/pkg/detectors/blablabus" "github.com/trufflesecurity/trufflehog/v3/pkg/detectors/blazemeter" "github.com/trufflesecurity/trufflehog/v3/pkg/detectors/blitapp" "github.com/trufflesecurity/trufflehog/v3/pkg/detectors/blocknative" @@ -192,7 +192,6 @@ import ( "github.com/trufflesecurity/trufflehog/v3/pkg/detectors/databox" "github.com/trufflesecurity/trufflehog/v3/pkg/detectors/databrickstoken" "github.com/trufflesecurity/trufflehog/v3/pkg/detectors/datadogtoken" - "github.com/trufflesecurity/trufflehog/v3/pkg/detectors/datafire" "github.com/trufflesecurity/trufflehog/v3/pkg/detectors/datagov" "github.com/trufflesecurity/trufflehog/v3/pkg/detectors/deepai" "github.com/trufflesecurity/trufflehog/v3/pkg/detectors/deepgram" @@ -266,7 +265,6 @@ import ( "github.com/trufflesecurity/trufflehog/v3/pkg/detectors/flightstats" "github.com/trufflesecurity/trufflehog/v3/pkg/detectors/float" "github.com/trufflesecurity/trufflehog/v3/pkg/detectors/flowdash" - "github.com/trufflesecurity/trufflehog/v3/pkg/detectors/flowdock" "github.com/trufflesecurity/trufflehog/v3/pkg/detectors/flowflu" "github.com/trufflesecurity/trufflehog/v3/pkg/detectors/flutterwave" "github.com/trufflesecurity/trufflehog/v3/pkg/detectors/fmfw" @@ -305,7 +303,6 @@ import ( "github.com/trufflesecurity/trufflehog/v3/pkg/detectors/gitlabv2" "github.com/trufflesecurity/trufflehog/v3/pkg/detectors/gitter" "github.com/trufflesecurity/trufflehog/v3/pkg/detectors/glassnode" - "github.com/trufflesecurity/trufflehog/v3/pkg/detectors/glitterlyapi" "github.com/trufflesecurity/trufflehog/v3/pkg/detectors/gocanvas" "github.com/trufflesecurity/trufflehog/v3/pkg/detectors/gocardless" "github.com/trufflesecurity/trufflehog/v3/pkg/detectors/goodday" @@ -316,7 +313,6 @@ import ( "github.com/trufflesecurity/trufflehog/v3/pkg/detectors/guardianapi" "github.com/trufflesecurity/trufflehog/v3/pkg/detectors/gumroad" "github.com/trufflesecurity/trufflehog/v3/pkg/detectors/gyazo" - "github.com/trufflesecurity/trufflehog/v3/pkg/detectors/happi" "github.com/trufflesecurity/trufflehog/v3/pkg/detectors/happyscribe" "github.com/trufflesecurity/trufflehog/v3/pkg/detectors/harvest" "github.com/trufflesecurity/trufflehog/v3/pkg/detectors/heatmapapi" @@ -388,6 +384,7 @@ import ( "github.com/trufflesecurity/trufflehog/v3/pkg/detectors/livestorm" "github.com/trufflesecurity/trufflehog/v3/pkg/detectors/loadmill" "github.com/trufflesecurity/trufflehog/v3/pkg/detectors/locationiq" + "github.com/trufflesecurity/trufflehog/v3/pkg/detectors/loggly" "github.com/trufflesecurity/trufflehog/v3/pkg/detectors/loginradius" "github.com/trufflesecurity/trufflehog/v3/pkg/detectors/lokalisetoken" "github.com/trufflesecurity/trufflehog/v3/pkg/detectors/loyverse" @@ -533,7 +530,6 @@ import ( "github.com/trufflesecurity/trufflehog/v3/pkg/detectors/qase" "github.com/trufflesecurity/trufflehog/v3/pkg/detectors/qualaroo" "github.com/trufflesecurity/trufflehog/v3/pkg/detectors/qubole" - "github.com/trufflesecurity/trufflehog/v3/pkg/detectors/quickmetrics" "github.com/trufflesecurity/trufflehog/v3/pkg/detectors/rapidapi" "github.com/trufflesecurity/trufflehog/v3/pkg/detectors/rawg" "github.com/trufflesecurity/trufflehog/v3/pkg/detectors/razorpay" @@ -714,6 +710,7 @@ import ( "github.com/trufflesecurity/trufflehog/v3/pkg/detectors/urlscan" "github.com/trufflesecurity/trufflehog/v3/pkg/detectors/userflow" "github.com/trufflesecurity/trufflehog/v3/pkg/detectors/userstack" + "github.com/trufflesecurity/trufflehog/v3/pkg/detectors/vagrantcloudpersonaltoken" "github.com/trufflesecurity/trufflehog/v3/pkg/detectors/vatlayer" "github.com/trufflesecurity/trufflehog/v3/pkg/detectors/vbout" "github.com/trufflesecurity/trufflehog/v3/pkg/detectors/vercel" @@ -1062,7 +1059,6 @@ func DefaultDetectors() []detectors.Detector { deepgram.Scanner{}, brandfetch.Scanner{}, typeform.Scanner{}, - blablabus.Scanner{}, fxmarket.Scanner{}, ipapi.Scanner{}, clearbit.Scanner{}, @@ -1188,7 +1184,6 @@ func DefaultDetectors() []detectors.Detector { restpackscreenshotapi.Scanner{}, shortcut.Scanner{}, // nasdaqdatalink.Scanner{}, - quickmetrics.Scanner{}, neutrinoapi.Scanner{}, bitmex.Scanner{}, deepai.Scanner{}, @@ -1214,7 +1209,6 @@ func DefaultDetectors() []detectors.Detector { scraperbox.Scanner{}, passbase.Scanner{}, ticketmaster.Scanner{}, - datafire.Scanner{}, iexcloud.Scanner{}, partnerstack.Scanner{}, qubole.Scanner{}, @@ -1248,7 +1242,6 @@ func DefaultDetectors() []detectors.Detector { scrapeowl.Scanner{}, rebrandly.Scanner{}, dandelion.Scanner{}, - baseapiio.Scanner{}, purestake.Scanner{}, carboninterface.Scanner{}, signaturit.Scanner{}, @@ -1366,7 +1359,6 @@ func DefaultDetectors() []detectors.Detector { ditto.Scanner{}, buddyns.Scanner{}, checio.Scanner{}, - happi.Scanner{}, kucoin.Scanner{}, eightxeight.Scanner{}, avazapersonalaccesstoken.Scanner{}, @@ -1403,7 +1395,6 @@ func DefaultDetectors() []detectors.Detector { convier.Scanner{}, loadmill.Scanner{}, magicbell.Scanner{}, - glitterlyapi.Scanner{}, apitemplate.Scanner{}, knapsackpro.Scanner{}, twitter.Scanner{}, @@ -1437,7 +1428,6 @@ func DefaultDetectors() []detectors.Detector { flowdash.Scanner{}, lunchmoney.Scanner{}, atera.Scanner{}, - flowdock.Scanner{}, parsehub.Scanner{}, voodoosms.Scanner{}, yelp.Scanner{}, @@ -1551,11 +1541,15 @@ func DefaultDetectors() []detectors.Detector { salesforce.Scanner{}, sourcegraph.Scanner{}, tailscale.Scanner{}, + loggly.Scanner{}, web3storage.Scanner{}, &ramp.Scanner{}, &anthropic.Scanner{}, &sourcegraphcody.Scanner{}, voiceflow.Scanner{}, + ip2location.Scanner{}, + vagrantcloudpersonaltoken.Scanner{}, + openvpn.Scanner{}, } } diff --git a/pkg/engine/engine.go b/pkg/engine/engine.go index 83642f9f6049..370c44db6570 100644 --- a/pkg/engine/engine.go +++ b/pkg/engine/engine.go @@ -3,14 +3,11 @@ package engine import ( "bytes" "fmt" - "reflect" "runtime" - "strings" "sync" "sync/atomic" "time" - ahocorasick "github.com/BobuSumisu/aho-corasick" lru "github.com/hashicorp/golang-lru" "google.golang.org/protobuf/proto" @@ -66,9 +63,8 @@ type Engine struct { onlyVerified bool printAvgDetectorTime bool - // prefilter is a ahocorasick struct used for doing efficient string - // matching given a set of words (keywords from the rules in the config) - prefilter ahocorasick.Trie + // ahoCorasickHandler manages the Aho-Corasick trie and related keyword lookups. + ahoCorasickCore *AhoCorasickCore // Engine synchronization primitives. sourceManager *sources.SourceManager @@ -93,9 +89,10 @@ type Engine struct { dedupeCache *lru.Cache } -type EngineOption func(*Engine) +// Option is used to configure the engine during initialization using functional options. +type Option func(*Engine) -func WithConcurrency(concurrency uint8) EngineOption { +func WithConcurrency(concurrency uint8) Option { return func(e *Engine) { e.concurrency = concurrency } @@ -103,7 +100,7 @@ func WithConcurrency(concurrency uint8) EngineOption { const ignoreTag = "trufflehog:ignore" -func WithDetectors(verify bool, d ...detectors.Detector) EngineOption { +func WithDetectors(verify bool, d ...detectors.Detector) Option { return func(e *Engine) { if e.detectors == nil { e.detectors = make(map[bool][]detectors.Detector) @@ -116,7 +113,7 @@ func WithDetectors(verify bool, d ...detectors.Detector) EngineOption { } } -func WithDecoders(decoders ...decoders.Decoder) EngineOption { +func WithDecoders(decoders ...decoders.Decoder) Option { return func(e *Engine) { e.decoders = decoders } @@ -124,14 +121,14 @@ func WithDecoders(decoders ...decoders.Decoder) EngineOption { // WithFilterUnverified sets the filterUnverified flag on the engine. If set to // true, the engine will only return the first unverified result for a chunk for a detector. -func WithFilterUnverified(filter bool) EngineOption { +func WithFilterUnverified(filter bool) Option { return func(e *Engine) { e.filterUnverified = filter } } // WithFilterEntropy filters out unverified results using Shannon entropy. -func WithFilterEntropy(entropy float64) EngineOption { +func WithFilterEntropy(entropy float64) Option { return func(e *Engine) { if entropy > 0 { e.filterEntropy = &entropy @@ -141,7 +138,7 @@ func WithFilterEntropy(entropy float64) EngineOption { // WithOnlyVerified sets the onlyVerified flag on the engine. If set to true, // the engine will only print verified results. -func WithOnlyVerified(onlyVerified bool) EngineOption { +func WithOnlyVerified(onlyVerified bool) Option { return func(e *Engine) { e.onlyVerified = onlyVerified } @@ -153,7 +150,7 @@ func WithOnlyVerified(onlyVerified bool) EngineOption { // the engine is configured to print the results. // Calculating the average time taken by each detector is an expensive operation // and should be avoided unless specified by the user. -func WithPrintAvgDetectorTime(printAvgDetectorTime bool) EngineOption { +func WithPrintAvgDetectorTime(printAvgDetectorTime bool) Option { return func(e *Engine) { e.printAvgDetectorTime = printAvgDetectorTime } @@ -163,7 +160,7 @@ func WithPrintAvgDetectorTime(printAvgDetectorTime bool) EngineOption { // the filterFunc returns true, the detector will be included for scanning. // This option applies to the existing list of detectors configured, so the // order this option appears matters. All filtering happens before scanning. -func WithFilterDetectors(filterFunc func(detectors.Detector) bool) EngineOption { +func WithFilterDetectors(filterFunc func(detectors.Detector) bool) Option { return func(e *Engine) { // If no detectors are configured, do nothing. if e.detectors == nil { @@ -175,7 +172,7 @@ func WithFilterDetectors(filterFunc func(detectors.Detector) bool) EngineOption } // WithPrinter sets the Printer on the engine. -func WithPrinter(printer Printer) EngineOption { +func WithPrinter(printer Printer) Option { return func(e *Engine) { e.printer = printer } @@ -269,32 +266,60 @@ func (e *Engine) DetectorAvgTime() map[string][]time.Duration { return avgTime } -// Start the engine with options. -func Start(ctx context.Context, options ...EngineOption) (*Engine, error) { - const ( - defaultChannelBuffer = 1 - // TODO (ahrav): Determine the optimal cache size. - cacheSize = 512 // number of entries in the LRU cache - ) +// Start initializes and activates the engine's processing pipeline. +// It sets up various default configurations, prepares lookup structures for +// detectors, conducts basic sanity checks, and kickstarts all necessary workers. +// Once started, the engine begins processing input data to identify secrets. +func Start(ctx context.Context, options ...Option) (*Engine, error) { + e := &Engine{} + + if err := e.initialize(ctx, options...); err != nil { + return nil, err + } + e.setDefaults(ctx) + ctx.Logger().V(4).Info("setting up aho-corasick core") + e.ahoCorasickCore.Setup(ctx) + e.sanityChecks(ctx) + e.startWorkers(ctx) + + return e, nil +} + +const defaultChannelBuffer = 1 + +// initialize prepares the engine's internal structures. The LRU cache optimizes +// deduplication efforts, allowing the engine to quickly check if a chunk has +// been processed before, thereby saving computational overhead. +func (e *Engine) initialize(ctx context.Context, options ...Option) error { + // TODO (ahrav): Determine the optimal cache size. + const cacheSize = 512 // number of entries in the LRU cache cache, err := lru.New(cacheSize) if err != nil { - return nil, fmt.Errorf("failed to initialize LRU cache: %w", err) + return fmt.Errorf("failed to initialize LRU cache: %w", err) } - e := &Engine{ - detectableChunksChan: make(chan detectableChunk, defaultChannelBuffer), - results: make(chan detectors.ResultWithMetadata, defaultChannelBuffer), - dedupeCache: cache, - printer: new(output.PlainPrinter), // default printer - metrics: runtimeMetrics{Metrics: Metrics{scanStartTime: time.Now()}}, - } + // Channels are used for communication between different parts of the engine, + // ensuring that data flows smoothly without race conditions. + e.detectableChunksChan = make(chan detectableChunk, defaultChannelBuffer) + e.results = make(chan detectors.ResultWithMetadata, defaultChannelBuffer) + e.dedupeCache = cache + e.printer = new(output.PlainPrinter) + e.metrics = runtimeMetrics{Metrics: Metrics{scanStartTime: time.Now()}} for _, option := range options { option(e) } + ctx.Logger().V(4).Info("engine initialized") + e.ahoCorasickCore = NewAhoCorasickCore(e.detectors) - // Set defaults. + return nil +} + +// setDefaults ensures that if specific engine properties aren't provided, +// they're set to reasonable default values. It makes the engine robust to +// incomplete configuration. +func (e *Engine) setDefaults(ctx context.Context) { if e.concurrency == 0 { numCPU := runtime.NumCPU() ctx.Logger().Info("No concurrency specified, defaulting to max", "cpu", numCPU) @@ -302,12 +327,13 @@ func Start(ctx context.Context, options ...EngineOption) (*Engine, error) { } ctx.Logger().V(3).Info("engine started", "workers", e.concurrency) - // Create SourceManager. e.sourceManager = sources.NewManager( sources.WithConcurrentSources(int(e.concurrency)), sources.WithConcurrentUnits(int(e.concurrency)), + sources.WithBufferedOutput(defaultChannelBuffer), ) + // Default decoders handle common encoding formats. if len(e.decoders) == 0 { e.decoders = decoders.DefaultDecoders() } @@ -317,46 +343,30 @@ func Start(ctx context.Context, options ...EngineOption) (*Engine, error) { e.detectors[true] = DefaultDetectors() e.detectors[false] = []detectors.Detector{} } + ctx.Logger().V(4).Info("default engine options set") +} - // build ahocorasick prefilter for efficient string matching - // on keywords - keywords := []string{} - for _, d := range e.detectors[false] { - for _, kw := range d.Keywords() { - keywords = append(keywords, strings.ToLower(kw)) - } - } - for _, d := range e.detectors[true] { - for _, kw := range d.Keywords() { - keywords = append(keywords, strings.ToLower(kw)) - } - } - e.prefilter = *ahocorasick.NewTrieBuilder().AddStrings(keywords).Build() - - ctx.Logger().V(3).Info("loaded decoders", "count", len(e.decoders)) - ctx.Logger().V(3).Info("loaded detectors", - "total", len(e.detectors[true])+len(e.detectors[false]), - "verification_enabled", len(e.detectors[true]), - "verification_disabled", len(e.detectors[false]), - ) - - // Sanity check detectors for duplicate configuration. Only log in case - // a detector has been configured in a way that isn't represented by - // the DetectorID (type and version). - { - dets := append(e.detectors[true], e.detectors[false]...) - seenDetectors := make(map[config.DetectorID]struct{}, len(dets)) - for _, det := range dets { - id := config.GetDetectorID(det) - if _, ok := seenDetectors[id]; ok && id.ID != detectorspb.DetectorType_CustomRegex { - ctx.Logger().Info("possible duplicate detector configured", "detector", id) - } - seenDetectors[id] = struct{}{} +// Sanity check detectors for duplicate configuration. Only log in case +// a detector has been configured in a way that isn't represented by +// the DetectorID (type and version). +func (e *Engine) sanityChecks(ctx context.Context) { + dets := append(e.detectors[true], e.detectors[false]...) + seenDetectors := make(map[config.DetectorID]struct{}, len(dets)) + for _, det := range dets { + id := config.GetDetectorID(det) + if _, ok := seenDetectors[id]; ok && id.ID != detectorspb.DetectorType_CustomRegex { + ctx.Logger().Info("possible duplicate detector configured", "detector", id) } + seenDetectors[id] = struct{}{} } +} +// startWorkers initiates all necessary workers. Workers handle processing of +// chunks concurrently. Separating the initialization of different types of +// workers helps in scalability and makes it easier to diagnose issues. +func (e *Engine) startWorkers(ctx context.Context) { + // Scanner workers process input data and extract chunks for detectors. ctx.Logger().V(2).Info("starting scanner workers", "count", e.concurrency) - // Run the Secret scanner workers and Notifier pipelines. for worker := uint64(0); worker < uint64(e.concurrency); worker++ { e.workersWg.Add(1) go func() { @@ -367,6 +377,7 @@ func Start(ctx context.Context, options ...EngineOption) (*Engine, error) { }() } + // Detector workers apply keyword matching, regexes and API calls to detect secrets in chunks. const detectorWorkerMultiplier = 50 ctx.Logger().V(2).Info("starting detector workers", "count", e.concurrency*detectorWorkerMultiplier) for worker := uint64(0); worker < uint64(e.concurrency*detectorWorkerMultiplier); worker++ { @@ -379,6 +390,7 @@ func Start(ctx context.Context, options ...EngineOption) (*Engine, error) { }() } + // Notifier workers communicate detected issues to the user or any downstream systems. // We want 1/4th of the notifier workers as the number of scanner workers. const notifierWorkerRatio = 4 maxNotifierWorkers := 1 @@ -395,8 +407,6 @@ func Start(ctx context.Context, options ...EngineOption) (*Engine, error) { e.notifyResults(ctx) }() } - - return e, nil } // Finish waits for running sources to complete and workers to finish scanning @@ -445,64 +455,42 @@ type detectableChunk struct { func (e *Engine) detectorWorker(ctx context.Context) { var wgDetect sync.WaitGroup + // Reuse the same map to avoid allocations. + const avgDetectorsPerChunk = 2 + chunkSpecificDetectors := make(map[detectorspb.DetectorType]DetectorInfo, avgDetectorsPerChunk) for originalChunk := range e.ChunksChan() { for chunk := range sources.Chunker(originalChunk) { - matchedKeywords := make(map[string]struct{}) atomic.AddUint64(&e.metrics.BytesScanned, uint64(len(chunk.Data))) for _, decoder := range e.decoders { - var decoderType detectorspb.DecoderType - switch decoder.(type) { - case *decoders.UTF8: - decoderType = detectorspb.DecoderType_PLAIN - case *decoders.Base64: - decoderType = detectorspb.DecoderType_BASE64 - case *decoders.UTF16: - decoderType = detectorspb.DecoderType_UTF16 - default: - ctx.Logger().Info("unknown decoder type", "type", reflect.TypeOf(decoder).String()) - decoderType = detectorspb.DecoderType_UNKNOWN - } - decoded := decoder.FromChunk(chunk) - if decoded == nil { + ctx.Logger().V(4).Info("no decoder found for chunk", "chunk", chunk) continue } - // build a map of all keywords that were matched in the chunk - for _, m := range e.prefilter.MatchString(strings.ToLower(string(decoded.Data))) { - matchedKeywords[strings.ToLower(m.MatchString())] = struct{}{} + for _, match := range e.ahoCorasickCore.MatchString(string(decoded.Chunk.Data)) { + if !e.ahoCorasickCore.PopulateDetectorsByMatch(match, chunkSpecificDetectors) { + continue + } } - for verify, detectorsSet := range e.detectors { - for _, detector := range detectorsSet { - chunkContainsKeyword := false - for _, kw := range detector.Keywords() { - if _, ok := matchedKeywords[strings.ToLower(kw)]; ok { - chunkContainsKeyword = true - break - } - } - - if !chunkContainsKeyword { - continue - } - - decoded.Verify = verify - wgDetect.Add(1) - e.detectableChunksChan <- detectableChunk{ - chunk: *decoded, - detector: detector, - decoder: decoderType, - wgDoneFn: wgDetect.Done, - } + for k, detector := range chunkSpecificDetectors { + decoded.Chunk.Verify = detector.ShouldVerify + wgDetect.Add(1) + e.detectableChunksChan <- detectableChunk{ + chunk: *decoded.Chunk, + detector: detector, + decoder: decoded.DecoderType, + wgDoneFn: wgDetect.Done, } + delete(chunkSpecificDetectors, k) } } } atomic.AddUint64(&e.metrics.ChunksScanned, 1) } wgDetect.Wait() + ctx.Logger().V(4).Info("finished scanning chunks") } func (e *Engine) detectChunks(ctx context.Context) { @@ -635,7 +623,7 @@ func FragmentLineOffset(chunk *sources.Chunk, result *detectors.Result) (int64, if !found { return 0, false } - lineNumber := int64(bytes.Count(before, []byte("\n")) + 1) + lineNumber := int64(bytes.Count(before, []byte("\n"))) // If the line contains the ignore tag, we should ignore the result. endLine := bytes.Index(after, []byte("\n")) if endLine == -1 { diff --git a/pkg/engine/engine_test.go b/pkg/engine/engine_test.go index da89897994d9..4e9b2eda587f 100644 --- a/pkg/engine/engine_test.go +++ b/pkg/engine/engine_test.go @@ -32,7 +32,7 @@ func TestFragmentLineOffset(t *testing.T) { result: &detectors.Result{ Raw: []byte("secret here"), }, - expectedLine: 3, + expectedLine: 2, ignore: true, }, { @@ -43,7 +43,7 @@ func TestFragmentLineOffset(t *testing.T) { result: &detectors.Result{ Raw: []byte("secret here"), }, - expectedLine: 3, + expectedLine: 2, ignore: false, }, { @@ -54,7 +54,7 @@ func TestFragmentLineOffset(t *testing.T) { result: &detectors.Result{ Raw: []byte("secret here"), }, - expectedLine: 5, + expectedLine: 4, ignore: false, }, { @@ -65,7 +65,7 @@ func TestFragmentLineOffset(t *testing.T) { result: &detectors.Result{ Raw: []byte("secret\nhere"), }, - expectedLine: 5, + expectedLine: 4, ignore: false, }, { @@ -76,7 +76,7 @@ func TestFragmentLineOffset(t *testing.T) { result: &detectors.Result{ Raw: []byte("secret\nhere"), }, - expectedLine: 4, + expectedLine: 3, ignore: true, }, { @@ -87,7 +87,7 @@ func TestFragmentLineOffset(t *testing.T) { result: &detectors.Result{ Raw: []byte("secret here"), }, - expectedLine: 4, + expectedLine: 3, ignore: true, }, } diff --git a/pkg/engine/git_test.go b/pkg/engine/git_test.go index 821df94a27ac..ecfd1b589ab0 100644 --- a/pkg/engine/git_test.go +++ b/pkg/engine/git_test.go @@ -2,6 +2,7 @@ package engine import ( "os" + "runtime" "testing" "github.com/stretchr/testify/assert" @@ -120,9 +121,10 @@ func BenchmarkGitEngine(b *testing.B) { defer cancel() e, err := Start(ctx, - WithConcurrency(1), + WithConcurrency(uint8(runtime.NumCPU())), WithDecoders(decoders.DefaultDecoders()...), WithDetectors(false, DefaultDetectors()...), + WithPrinter(new(discardPrinter)), ) assert.Nil(b, err) @@ -133,6 +135,7 @@ func BenchmarkGitEngine(b *testing.B) { } }() + b.ResetTimer() for i := 0; i < b.N; i++ { // TODO: this is measuring the time it takes to initialize the source // and not to do the full scan diff --git a/pkg/handlers/archive_test.go b/pkg/handlers/archive_test.go index 5c371faa642b..009446c62b89 100644 --- a/pkg/handlers/archive_test.go +++ b/pkg/handlers/archive_test.go @@ -11,7 +11,7 @@ import ( "testing" "time" - diskbufferreader "github.com/bill-rich/disk-buffer-reader" + diskbufferreader "github.com/trufflesecurity/disk-buffer-reader" "github.com/stretchr/testify/assert" logContext "github.com/trufflesecurity/trufflehog/v3/pkg/context" diff --git a/pkg/handlers/handlers.go b/pkg/handlers/handlers.go index 5ff59a7a766f..131e77c963a4 100644 --- a/pkg/handlers/handlers.go +++ b/pkg/handlers/handlers.go @@ -4,7 +4,7 @@ import ( "context" "io" - diskbufferreader "github.com/bill-rich/disk-buffer-reader" + diskbufferreader "github.com/trufflesecurity/disk-buffer-reader" logContext "github.com/trufflesecurity/trufflehog/v3/pkg/context" "github.com/trufflesecurity/trufflehog/v3/pkg/sources" diff --git a/pkg/pb/detectorspb/detectors.pb.go b/pkg/pb/detectorspb/detectors.pb.go index ddfb3d4080a1..92d2b129c0f3 100644 --- a/pkg/pb/detectorspb/detectors.pb.go +++ b/pkg/pb/detectorspb/detectors.pb.go @@ -424,592 +424,606 @@ const ( DetectorType_Imagga DetectorType = 349 DetectorType_SMSApi DetectorType = 350 DetectorType_Distribusion DetectorType = 351 - DetectorType_Blablabus DetectorType = 352 - DetectorType_WordsApi DetectorType = 353 - DetectorType_Currencylayer DetectorType = 354 - DetectorType_Html2Pdf DetectorType = 355 - DetectorType_IPGeolocation DetectorType = 356 - DetectorType_Owlbot DetectorType = 357 - DetectorType_Cloudmersive DetectorType = 358 - DetectorType_Dynalist DetectorType = 359 - DetectorType_ExchangeRateAPI DetectorType = 360 - DetectorType_HolidayAPI DetectorType = 361 - DetectorType_Ipapi DetectorType = 362 - DetectorType_Marketstack DetectorType = 363 - DetectorType_Nutritionix DetectorType = 364 - DetectorType_Swell DetectorType = 365 - DetectorType_ClickupPersonalToken DetectorType = 366 - DetectorType_Nitro DetectorType = 367 - DetectorType_Rev DetectorType = 368 - DetectorType_RunRunIt DetectorType = 369 - DetectorType_Typeform DetectorType = 370 - DetectorType_Mixpanel DetectorType = 371 - DetectorType_Tradier DetectorType = 372 - DetectorType_Verifier DetectorType = 373 - DetectorType_Vouchery DetectorType = 374 - DetectorType_Alegra DetectorType = 375 - DetectorType_Audd DetectorType = 376 - DetectorType_Baremetrics DetectorType = 377 - DetectorType_Coinlib DetectorType = 378 - DetectorType_ExchangeRatesAPI DetectorType = 379 - DetectorType_CurrencyScoop DetectorType = 380 - DetectorType_FXMarket DetectorType = 381 - DetectorType_CurrencyCloud DetectorType = 382 - DetectorType_GetGeoAPI DetectorType = 383 - DetectorType_Abstract DetectorType = 384 - DetectorType_Billomat DetectorType = 385 - DetectorType_Dovico DetectorType = 386 - DetectorType_Bitbar DetectorType = 387 - DetectorType_Bugsnag DetectorType = 388 - DetectorType_AssemblyAI DetectorType = 389 - DetectorType_AdafruitIO DetectorType = 390 - DetectorType_Apify DetectorType = 391 - DetectorType_CoinGecko DetectorType = 392 - DetectorType_CryptoCompare DetectorType = 393 - DetectorType_Fullstory DetectorType = 394 - DetectorType_HelloSign DetectorType = 395 - DetectorType_Loyverse DetectorType = 396 - DetectorType_NetCore DetectorType = 397 - DetectorType_SauceLabs DetectorType = 398 - DetectorType_AlienVault DetectorType = 399 - DetectorType_Apiflash DetectorType = 401 - DetectorType_Coinlayer DetectorType = 402 - DetectorType_CurrentsAPI DetectorType = 403 - DetectorType_DataGov DetectorType = 404 - DetectorType_Enigma DetectorType = 405 - DetectorType_FinancialModelingPrep DetectorType = 406 - DetectorType_Geocodio DetectorType = 407 - DetectorType_HereAPI DetectorType = 408 - DetectorType_Macaddress DetectorType = 409 - DetectorType_OOPSpam DetectorType = 410 - DetectorType_ProtocolsIO DetectorType = 411 - DetectorType_ScraperAPI DetectorType = 412 - DetectorType_SecurityTrails DetectorType = 413 - DetectorType_TomorrowIO DetectorType = 414 - DetectorType_WorldCoinIndex DetectorType = 415 - DetectorType_FacePlusPlus DetectorType = 416 - DetectorType_Voicegain DetectorType = 417 - DetectorType_Deepgram DetectorType = 418 - DetectorType_VisualCrossing DetectorType = 419 - DetectorType_Finnhub DetectorType = 420 - DetectorType_Tiingo DetectorType = 421 - DetectorType_RingCentral DetectorType = 422 - DetectorType_Finage DetectorType = 423 - DetectorType_Edamam DetectorType = 424 - DetectorType_HypeAuditor DetectorType = 425 - DetectorType_Gengo DetectorType = 426 - DetectorType_Front DetectorType = 427 - DetectorType_Fleetbase DetectorType = 428 - DetectorType_Bubble DetectorType = 429 - DetectorType_Bannerbear DetectorType = 430 - DetectorType_Adzuna DetectorType = 431 - DetectorType_BitcoinAverage DetectorType = 432 - DetectorType_CommerceJS DetectorType = 433 - DetectorType_DetectLanguage DetectorType = 434 - DetectorType_FakeJSON DetectorType = 435 - DetectorType_Graphhopper DetectorType = 436 - DetectorType_Lexigram DetectorType = 437 - DetectorType_LinkPreview DetectorType = 438 - DetectorType_Numverify DetectorType = 439 - DetectorType_ProxyCrawl DetectorType = 440 - DetectorType_ZipCodeAPI DetectorType = 441 - DetectorType_Cometchat DetectorType = 442 - DetectorType_Keygen DetectorType = 443 - DetectorType_Mixcloud DetectorType = 444 - DetectorType_TatumIO DetectorType = 445 - DetectorType_Tmetric DetectorType = 446 - DetectorType_Lastfm DetectorType = 447 - DetectorType_Browshot DetectorType = 448 - DetectorType_JSONbin DetectorType = 449 - DetectorType_LocationIQ DetectorType = 450 - DetectorType_ScreenshotAPI DetectorType = 451 - DetectorType_WeatherStack DetectorType = 452 - DetectorType_Amadeus DetectorType = 453 - DetectorType_FourSquare DetectorType = 454 - DetectorType_Flickr DetectorType = 455 - DetectorType_ClickHelp DetectorType = 456 - DetectorType_Ambee DetectorType = 457 - DetectorType_Api2Cart DetectorType = 458 - DetectorType_Hypertrack DetectorType = 459 - DetectorType_KakaoTalk DetectorType = 460 - DetectorType_RiteKit DetectorType = 461 - DetectorType_Shutterstock DetectorType = 462 - DetectorType_Text2Data DetectorType = 463 - DetectorType_YouNeedABudget DetectorType = 464 - DetectorType_Cricket DetectorType = 465 - DetectorType_Filestack DetectorType = 466 - DetectorType_Gyazo DetectorType = 467 - DetectorType_Mavenlink DetectorType = 468 - DetectorType_Sheety DetectorType = 469 - DetectorType_Sportsmonk DetectorType = 470 - DetectorType_Stockdata DetectorType = 471 - DetectorType_Unsplash DetectorType = 472 - DetectorType_Allsports DetectorType = 473 - DetectorType_CalorieNinja DetectorType = 474 - DetectorType_WalkScore DetectorType = 475 - DetectorType_Strava DetectorType = 476 - DetectorType_Cicero DetectorType = 477 - DetectorType_IPQuality DetectorType = 478 - DetectorType_ParallelDots DetectorType = 479 - DetectorType_Roaring DetectorType = 480 - DetectorType_Mailsac DetectorType = 481 - DetectorType_Whoxy DetectorType = 482 - DetectorType_WorldWeather DetectorType = 483 - DetectorType_ApiFonica DetectorType = 484 - DetectorType_Aylien DetectorType = 485 - DetectorType_Geocode DetectorType = 486 - DetectorType_IconFinder DetectorType = 487 - DetectorType_Ipify DetectorType = 488 - DetectorType_LanguageLayer DetectorType = 489 - DetectorType_Lob DetectorType = 490 - DetectorType_OnWaterIO DetectorType = 491 - DetectorType_Pastebin DetectorType = 492 - DetectorType_PdfLayer DetectorType = 493 - DetectorType_Pixabay DetectorType = 494 - DetectorType_ReadMe DetectorType = 495 - DetectorType_VatLayer DetectorType = 496 - DetectorType_VirusTotal DetectorType = 497 - DetectorType_AirVisual DetectorType = 498 - DetectorType_Currencyfreaks DetectorType = 499 - DetectorType_Duffel DetectorType = 500 - DetectorType_FlatIO DetectorType = 501 - DetectorType_M3o DetectorType = 502 - DetectorType_Mesibo DetectorType = 503 - DetectorType_Openuv DetectorType = 504 - DetectorType_Snipcart DetectorType = 505 - DetectorType_Besttime DetectorType = 506 - DetectorType_Happyscribe DetectorType = 507 - DetectorType_Humanity DetectorType = 508 - DetectorType_Impala DetectorType = 509 - DetectorType_Loginradius DetectorType = 510 - DetectorType_AutoPilot DetectorType = 511 - DetectorType_Bitmex DetectorType = 512 - DetectorType_ClustDoc DetectorType = 513 - DetectorType_Messari DetectorType = 514 - DetectorType_PdfShift DetectorType = 515 - DetectorType_Poloniex DetectorType = 516 - DetectorType_RestpackHtmlToPdfAPI DetectorType = 517 - DetectorType_RestpackScreenshotAPI DetectorType = 518 - DetectorType_ShutterstockOAuth DetectorType = 519 - DetectorType_SkyBiometry DetectorType = 520 - DetectorType_AbuseIPDB DetectorType = 521 - DetectorType_AletheiaApi DetectorType = 522 - DetectorType_BlitApp DetectorType = 523 - DetectorType_Censys DetectorType = 524 - DetectorType_Cloverly DetectorType = 525 - DetectorType_CountryLayer DetectorType = 526 - DetectorType_FileIO DetectorType = 527 - DetectorType_FlightApi DetectorType = 528 - DetectorType_Geoapify DetectorType = 529 - DetectorType_IPinfoDB DetectorType = 530 - DetectorType_MediaStack DetectorType = 531 - DetectorType_NasdaqDataLink DetectorType = 532 - DetectorType_OpenCageData DetectorType = 533 - DetectorType_Paymongo DetectorType = 534 - DetectorType_PositionStack DetectorType = 535 - DetectorType_Rebrandly DetectorType = 536 - DetectorType_ScreenshotLayer DetectorType = 537 - DetectorType_Stytch DetectorType = 538 - DetectorType_Unplugg DetectorType = 539 - DetectorType_UPCDatabase DetectorType = 540 - DetectorType_UserStack DetectorType = 541 - DetectorType_Geocodify DetectorType = 542 - DetectorType_Newscatcher DetectorType = 543 - DetectorType_Nicereply DetectorType = 544 - DetectorType_Partnerstack DetectorType = 545 - DetectorType_Route4me DetectorType = 546 - DetectorType_Scrapeowl DetectorType = 547 - DetectorType_ScrapingDog DetectorType = 548 - DetectorType_Streak DetectorType = 549 - DetectorType_Veriphone DetectorType = 550 - DetectorType_Webscraping DetectorType = 551 - DetectorType_Zenscrape DetectorType = 552 - DetectorType_Zenserp DetectorType = 553 - DetectorType_CoinApi DetectorType = 554 - DetectorType_Gitter DetectorType = 555 - DetectorType_Host DetectorType = 556 - DetectorType_Iexcloud DetectorType = 557 - DetectorType_Restpack DetectorType = 558 - DetectorType_ScraperBox DetectorType = 559 - DetectorType_ScrapingAnt DetectorType = 560 - DetectorType_SerpStack DetectorType = 561 - DetectorType_SmartyStreets DetectorType = 562 - DetectorType_TicketMaster DetectorType = 563 - DetectorType_AviationStack DetectorType = 564 - DetectorType_BombBomb DetectorType = 565 - DetectorType_Commodities DetectorType = 566 - DetectorType_Dfuse DetectorType = 567 - DetectorType_EdenAI DetectorType = 568 - DetectorType_Glassnode DetectorType = 569 - DetectorType_Guru DetectorType = 570 - DetectorType_Hive DetectorType = 571 - DetectorType_Hiveage DetectorType = 572 - DetectorType_Kickbox DetectorType = 573 - DetectorType_Passbase DetectorType = 574 - DetectorType_PostageApp DetectorType = 575 - DetectorType_PureStake DetectorType = 576 - DetectorType_Qubole DetectorType = 577 - DetectorType_CarbonInterface DetectorType = 578 - DetectorType_Intrinio DetectorType = 579 - DetectorType_QuickMetrics DetectorType = 580 - DetectorType_ScrapeStack DetectorType = 581 - DetectorType_TechnicalAnalysisApi DetectorType = 582 - DetectorType_Urlscan DetectorType = 583 - DetectorType_BaseApiIO DetectorType = 584 - DetectorType_DailyCO DetectorType = 585 - DetectorType_TLy DetectorType = 586 - DetectorType_Shortcut DetectorType = 587 - DetectorType_Appfollow DetectorType = 588 - DetectorType_Thinkific DetectorType = 589 - DetectorType_Feedly DetectorType = 590 - DetectorType_Stitchdata DetectorType = 591 - DetectorType_Fetchrss DetectorType = 592 - DetectorType_Signupgenius DetectorType = 593 - DetectorType_Signaturit DetectorType = 594 - DetectorType_Optimizely DetectorType = 595 - DetectorType_OcrSpace DetectorType = 596 - DetectorType_WeatherBit DetectorType = 597 - DetectorType_BuddyNS DetectorType = 598 - DetectorType_ZipAPI DetectorType = 599 - DetectorType_ZipBooks DetectorType = 600 - DetectorType_Onedesk DetectorType = 601 - DetectorType_Bugherd DetectorType = 602 - DetectorType_Blazemeter DetectorType = 603 - DetectorType_Autodesk DetectorType = 604 - DetectorType_Tru DetectorType = 605 - DetectorType_UnifyID DetectorType = 606 - DetectorType_Trimble DetectorType = 607 - DetectorType_Smooch DetectorType = 608 - DetectorType_Semaphore DetectorType = 609 - DetectorType_Telnyx DetectorType = 610 - DetectorType_Signalwire DetectorType = 611 - DetectorType_Textmagic DetectorType = 612 - DetectorType_Serphouse DetectorType = 613 - DetectorType_Planyo DetectorType = 614 - DetectorType_Simplybook DetectorType = 615 - DetectorType_Vyte DetectorType = 616 - DetectorType_Nylas DetectorType = 617 - DetectorType_Squareup DetectorType = 618 - DetectorType_Dandelion DetectorType = 619 - DetectorType_DataFire DetectorType = 620 - DetectorType_DeepAI DetectorType = 621 - DetectorType_MeaningCloud DetectorType = 622 - DetectorType_NeutrinoApi DetectorType = 623 - DetectorType_Storecove DetectorType = 624 - DetectorType_Shipday DetectorType = 625 - DetectorType_Sentiment DetectorType = 626 - DetectorType_StreamChatMessaging DetectorType = 627 - DetectorType_TeamworkCRM DetectorType = 628 - DetectorType_TeamworkDesk DetectorType = 629 - DetectorType_TeamworkSpaces DetectorType = 630 - DetectorType_TheOddsApi DetectorType = 631 - DetectorType_Apacta DetectorType = 632 - DetectorType_GetSandbox DetectorType = 633 - DetectorType_Happi DetectorType = 634 - DetectorType_Oanda DetectorType = 635 - DetectorType_FastForex DetectorType = 636 - DetectorType_APIMatic DetectorType = 637 - DetectorType_VersionEye DetectorType = 638 - DetectorType_EagleEyeNetworks DetectorType = 639 - DetectorType_ThousandEyes DetectorType = 640 - DetectorType_SelectPDF DetectorType = 641 - DetectorType_Flightstats DetectorType = 642 - DetectorType_ChecIO DetectorType = 643 - DetectorType_Manifest DetectorType = 644 - DetectorType_ApiScience DetectorType = 645 - DetectorType_AppSynergy DetectorType = 646 - DetectorType_Caflou DetectorType = 647 - DetectorType_Caspio DetectorType = 648 - DetectorType_ChecklyHQ DetectorType = 649 - DetectorType_CloudElements DetectorType = 650 - DetectorType_DronaHQ DetectorType = 651 - DetectorType_Enablex DetectorType = 652 - DetectorType_Fmfw DetectorType = 653 - DetectorType_GoodDay DetectorType = 654 - DetectorType_Luno DetectorType = 655 - DetectorType_Meistertask DetectorType = 656 - DetectorType_Mindmeister DetectorType = 657 - DetectorType_PeopleDataLabs DetectorType = 658 - DetectorType_ScraperSite DetectorType = 659 - DetectorType_Scrapfly DetectorType = 660 - DetectorType_SimplyNoted DetectorType = 661 - DetectorType_TravelPayouts DetectorType = 662 - DetectorType_WebScraper DetectorType = 663 - DetectorType_Convier DetectorType = 664 - DetectorType_Courier DetectorType = 665 - DetectorType_Ditto DetectorType = 666 - DetectorType_Findl DetectorType = 667 - DetectorType_Lendflow DetectorType = 668 - DetectorType_Moderation DetectorType = 669 - DetectorType_Opendatasoft DetectorType = 670 - DetectorType_Podio DetectorType = 671 - DetectorType_Rockset DetectorType = 672 - DetectorType_Rownd DetectorType = 673 - DetectorType_Shotstack DetectorType = 674 - DetectorType_Swiftype DetectorType = 675 - DetectorType_Twitter DetectorType = 676 - DetectorType_Honey DetectorType = 677 - DetectorType_Freshdesk DetectorType = 678 - DetectorType_Upwave DetectorType = 679 - DetectorType_Fountain DetectorType = 680 - DetectorType_Freshbooks DetectorType = 681 - DetectorType_Mite DetectorType = 682 - DetectorType_Deputy DetectorType = 683 - DetectorType_Beebole DetectorType = 684 - DetectorType_Cashboard DetectorType = 685 - DetectorType_Kanban DetectorType = 686 - DetectorType_Worksnaps DetectorType = 687 - DetectorType_MyIntervals DetectorType = 688 - DetectorType_InvoiceOcean DetectorType = 689 - DetectorType_Sherpadesk DetectorType = 690 - DetectorType_Mrticktock DetectorType = 691 - DetectorType_Chatfule DetectorType = 692 - DetectorType_Aeroworkflow DetectorType = 693 - DetectorType_Emailoctopus DetectorType = 694 - DetectorType_Fusebill DetectorType = 695 - DetectorType_Geckoboard DetectorType = 696 - DetectorType_Gosquared DetectorType = 697 - DetectorType_Moonclerk DetectorType = 698 - DetectorType_Paymoapp DetectorType = 699 - DetectorType_Mixmax DetectorType = 700 - DetectorType_Processst DetectorType = 701 - DetectorType_Repairshopr DetectorType = 702 - DetectorType_Goshippo DetectorType = 703 - DetectorType_Sigopt DetectorType = 704 - DetectorType_Sugester DetectorType = 705 - DetectorType_Viewneo DetectorType = 706 - DetectorType_BoostNote DetectorType = 707 - DetectorType_CaptainData DetectorType = 708 - DetectorType_Checkvist DetectorType = 709 - DetectorType_Cliengo DetectorType = 710 - DetectorType_Cloze DetectorType = 711 - DetectorType_FormIO DetectorType = 712 - DetectorType_FormBucket DetectorType = 713 - DetectorType_GoCanvas DetectorType = 714 - DetectorType_MadKudu DetectorType = 715 - DetectorType_NozbeTeams DetectorType = 716 - DetectorType_Papyrs DetectorType = 717 - DetectorType_SuperNotesAPI DetectorType = 718 - DetectorType_Tallyfy DetectorType = 719 - DetectorType_ZenkitAPI DetectorType = 720 - DetectorType_CloudImage DetectorType = 721 - DetectorType_UploadCare DetectorType = 722 - DetectorType_Borgbase DetectorType = 723 - DetectorType_Pipedream DetectorType = 724 - DetectorType_Sirv DetectorType = 725 - DetectorType_Diffbot DetectorType = 726 - DetectorType_EightxEight DetectorType = 727 - DetectorType_Sendoso DetectorType = 728 - DetectorType_Printfection DetectorType = 729 - DetectorType_Authorize DetectorType = 730 - DetectorType_PandaScore DetectorType = 731 - DetectorType_Paymo DetectorType = 732 - DetectorType_AvazaPersonalAccessToken DetectorType = 733 - DetectorType_PlanviewLeanKit DetectorType = 734 - DetectorType_Livestorm DetectorType = 735 - DetectorType_KuCoin DetectorType = 736 - DetectorType_MetaAPI DetectorType = 737 - DetectorType_NiceHash DetectorType = 738 - DetectorType_CexIO DetectorType = 739 - DetectorType_Klipfolio DetectorType = 740 - DetectorType_Dynatrace DetectorType = 741 - DetectorType_MollieAPIKey DetectorType = 742 - DetectorType_MollieAccessToken DetectorType = 743 - DetectorType_BasisTheory DetectorType = 744 - DetectorType_Nordigen DetectorType = 745 - DetectorType_FlagsmithEnvironmentKey DetectorType = 746 - DetectorType_FlagsmithToken DetectorType = 747 - DetectorType_Mux DetectorType = 748 - DetectorType_Column DetectorType = 749 - DetectorType_Sendbird DetectorType = 750 - DetectorType_SendbirdOrganizationAPI DetectorType = 751 - DetectorType_Midise DetectorType = 752 - DetectorType_Mockaroo DetectorType = 753 - DetectorType_Image4 DetectorType = 754 - DetectorType_Pinata DetectorType = 755 - DetectorType_BrowserStack DetectorType = 756 - DetectorType_CrossBrowserTesting DetectorType = 757 - DetectorType_Loadmill DetectorType = 758 - DetectorType_TestingBot DetectorType = 759 - DetectorType_KnapsackPro DetectorType = 760 - DetectorType_Qase DetectorType = 761 - DetectorType_Dareboost DetectorType = 762 - DetectorType_GTMetrix DetectorType = 763 - DetectorType_Holistic DetectorType = 764 - DetectorType_Parsers DetectorType = 765 - DetectorType_ScrutinizerCi DetectorType = 766 - DetectorType_SonarCloud DetectorType = 767 - DetectorType_APITemplate DetectorType = 768 - DetectorType_ConversionTools DetectorType = 769 - DetectorType_CraftMyPDF DetectorType = 770 - DetectorType_ExportSDK DetectorType = 771 - DetectorType_GlitterlyAPI DetectorType = 772 - DetectorType_Hybiscus DetectorType = 773 - DetectorType_Miro DetectorType = 774 - DetectorType_Statuspage DetectorType = 775 - DetectorType_Statuspal DetectorType = 776 - DetectorType_Teletype DetectorType = 777 - DetectorType_TimeCamp DetectorType = 778 - DetectorType_Userflow DetectorType = 779 - DetectorType_Wistia DetectorType = 780 - DetectorType_SportRadar DetectorType = 781 - DetectorType_UptimeRobot DetectorType = 782 - DetectorType_Codequiry DetectorType = 783 - DetectorType_ExtractorAPI DetectorType = 784 - DetectorType_Signable DetectorType = 785 - DetectorType_MagicBell DetectorType = 786 - DetectorType_Stormboard DetectorType = 787 - DetectorType_Apilayer DetectorType = 788 - DetectorType_Disqus DetectorType = 789 - DetectorType_Woopra DetectorType = 790 - DetectorType_Paperform DetectorType = 791 - DetectorType_Gumroad DetectorType = 792 - DetectorType_Paydirtapp DetectorType = 793 - DetectorType_Detectify DetectorType = 794 - DetectorType_Statuscake DetectorType = 795 - DetectorType_Jumpseller DetectorType = 796 - DetectorType_LunchMoney DetectorType = 797 - DetectorType_Rosette DetectorType = 798 - DetectorType_Yelp DetectorType = 799 - DetectorType_Atera DetectorType = 800 - DetectorType_EcoStruxureIT DetectorType = 801 - DetectorType_Aha DetectorType = 802 - DetectorType_Parsehub DetectorType = 803 - DetectorType_PackageCloud DetectorType = 804 - DetectorType_Cloudsmith DetectorType = 805 - DetectorType_Flowdash DetectorType = 806 - DetectorType_Flowdock DetectorType = 807 - DetectorType_Fibery DetectorType = 808 - DetectorType_Typetalk DetectorType = 809 - DetectorType_VoodooSMS DetectorType = 810 - DetectorType_ZulipChat DetectorType = 811 - DetectorType_Formcraft DetectorType = 812 - DetectorType_Iexapis DetectorType = 813 - DetectorType_Reachmail DetectorType = 814 - DetectorType_Chartmogul DetectorType = 815 - DetectorType_Appointedd DetectorType = 816 - DetectorType_Wit DetectorType = 817 - DetectorType_RechargePayments DetectorType = 818 - DetectorType_Diggernaut DetectorType = 819 - DetectorType_MonkeyLearn DetectorType = 820 - DetectorType_Duply DetectorType = 821 - DetectorType_Postbacks DetectorType = 822 - DetectorType_Collect2 DetectorType = 823 - DetectorType_ZenRows DetectorType = 824 - DetectorType_Zipcodebase DetectorType = 825 - DetectorType_Tefter DetectorType = 826 - DetectorType_Twist DetectorType = 827 - DetectorType_BraintreePayments DetectorType = 828 - DetectorType_CloudConvert DetectorType = 829 - DetectorType_Grafana DetectorType = 830 - DetectorType_ConvertApi DetectorType = 831 - DetectorType_Transferwise DetectorType = 832 - DetectorType_Bulksms DetectorType = 833 - DetectorType_Databox DetectorType = 834 - DetectorType_Onesignal DetectorType = 835 - DetectorType_Rentman DetectorType = 836 - DetectorType_Parseur DetectorType = 837 - DetectorType_Docparser DetectorType = 838 - DetectorType_Formsite DetectorType = 839 - DetectorType_Tickettailor DetectorType = 840 - DetectorType_Lemlist DetectorType = 841 - DetectorType_Prodpad DetectorType = 842 - DetectorType_Formstack DetectorType = 843 - DetectorType_Codeclimate DetectorType = 844 - DetectorType_Codemagic DetectorType = 845 - DetectorType_Vbout DetectorType = 846 - DetectorType_Nightfall DetectorType = 847 - DetectorType_FlightLabs DetectorType = 848 - DetectorType_SpeechTextAI DetectorType = 849 - DetectorType_PollsAPI DetectorType = 850 - DetectorType_SimFin DetectorType = 851 - DetectorType_Scalr DetectorType = 852 - DetectorType_Kanbantool DetectorType = 853 - DetectorType_Brightlocal DetectorType = 854 - DetectorType_Hotwire DetectorType = 855 - DetectorType_Instabot DetectorType = 856 - DetectorType_Timekit DetectorType = 857 - DetectorType_Interseller DetectorType = 858 - DetectorType_Mojohelpdesk DetectorType = 859 - DetectorType_Createsend DetectorType = 860 - DetectorType_Getresponse DetectorType = 861 - DetectorType_Dynadot DetectorType = 862 - DetectorType_Demio DetectorType = 863 - DetectorType_Tokeet DetectorType = 864 - DetectorType_Myexperiment DetectorType = 865 - DetectorType_Copyscape DetectorType = 866 - DetectorType_Besnappy DetectorType = 867 - DetectorType_Salesmate DetectorType = 868 - DetectorType_Heatmapapi DetectorType = 869 - DetectorType_Websitepulse DetectorType = 870 - DetectorType_Uclassify DetectorType = 871 - DetectorType_Convert DetectorType = 872 - DetectorType_PDFmyURL DetectorType = 873 - DetectorType_Api2Convert DetectorType = 874 - DetectorType_Opsgenie DetectorType = 875 - DetectorType_Gemini DetectorType = 876 - DetectorType_Honeycomb DetectorType = 877 - DetectorType_KalturaAppToken DetectorType = 878 - DetectorType_KalturaSession DetectorType = 879 - DetectorType_BitGo DetectorType = 880 - DetectorType_Optidash DetectorType = 881 - DetectorType_Imgix DetectorType = 882 - DetectorType_ImageToText DetectorType = 883 - DetectorType_Page2Images DetectorType = 884 - DetectorType_Quickbase DetectorType = 885 - DetectorType_Redbooth DetectorType = 886 - DetectorType_Nubela DetectorType = 887 - DetectorType_Infobip DetectorType = 888 - DetectorType_Uproc DetectorType = 889 - DetectorType_Supportbee DetectorType = 890 - DetectorType_Aftership DetectorType = 891 - DetectorType_Edusign DetectorType = 892 - DetectorType_Teamup DetectorType = 893 - DetectorType_Workday DetectorType = 894 - DetectorType_MongoDB DetectorType = 895 - DetectorType_NGC DetectorType = 896 - DetectorType_DigitalOceanV2 DetectorType = 897 - DetectorType_SQLServer DetectorType = 898 - DetectorType_FTP DetectorType = 899 - DetectorType_Redis DetectorType = 900 - DetectorType_LDAP DetectorType = 901 - DetectorType_Shopify DetectorType = 902 - DetectorType_RabbitMQ DetectorType = 903 - DetectorType_CustomRegex DetectorType = 904 - DetectorType_Etherscan DetectorType = 905 - DetectorType_Infura DetectorType = 906 - DetectorType_Alchemy DetectorType = 907 - DetectorType_BlockNative DetectorType = 908 - DetectorType_Moralis DetectorType = 909 - DetectorType_BscScan DetectorType = 910 - DetectorType_CoinMarketCap DetectorType = 911 - DetectorType_Percy DetectorType = 912 - DetectorType_TinesWebhook DetectorType = 913 - DetectorType_Pulumi DetectorType = 914 - DetectorType_SupabaseToken DetectorType = 915 - DetectorType_NuGetApiKey DetectorType = 916 - DetectorType_Aiven DetectorType = 917 - DetectorType_Prefect DetectorType = 918 - DetectorType_Docusign DetectorType = 919 - DetectorType_Couchbase DetectorType = 920 - DetectorType_Dockerhub DetectorType = 921 - DetectorType_TrufflehogEnterprise DetectorType = 922 - DetectorType_EnvoyApiKey DetectorType = 923 - DetectorType_GitHubOauth2 DetectorType = 924 - DetectorType_Salesforce DetectorType = 925 - DetectorType_HuggingFace DetectorType = 926 - DetectorType_Snowflake DetectorType = 927 - DetectorType_Sourcegraph DetectorType = 928 - DetectorType_Tailscale DetectorType = 929 - DetectorType_Web3Storage DetectorType = 930 - DetectorType_AzureStorage DetectorType = 931 - DetectorType_PlanetScaleDb DetectorType = 932 - DetectorType_Anthropic DetectorType = 933 - DetectorType_Ramp DetectorType = 934 - DetectorType_Klaviyo DetectorType = 935 - DetectorType_SourcegraphCody DetectorType = 936 - DetectorType_Voiceflow DetectorType = 937 - DetectorType_Privacy DetectorType = 938 + // Deprecated: Do not use. + DetectorType_Blablabus DetectorType = 352 + DetectorType_WordsApi DetectorType = 353 + DetectorType_Currencylayer DetectorType = 354 + DetectorType_Html2Pdf DetectorType = 355 + DetectorType_IPGeolocation DetectorType = 356 + DetectorType_Owlbot DetectorType = 357 + DetectorType_Cloudmersive DetectorType = 358 + DetectorType_Dynalist DetectorType = 359 + DetectorType_ExchangeRateAPI DetectorType = 360 + DetectorType_HolidayAPI DetectorType = 361 + DetectorType_Ipapi DetectorType = 362 + DetectorType_Marketstack DetectorType = 363 + DetectorType_Nutritionix DetectorType = 364 + DetectorType_Swell DetectorType = 365 + DetectorType_ClickupPersonalToken DetectorType = 366 + DetectorType_Nitro DetectorType = 367 + DetectorType_Rev DetectorType = 368 + DetectorType_RunRunIt DetectorType = 369 + DetectorType_Typeform DetectorType = 370 + DetectorType_Mixpanel DetectorType = 371 + DetectorType_Tradier DetectorType = 372 + DetectorType_Verifier DetectorType = 373 + DetectorType_Vouchery DetectorType = 374 + DetectorType_Alegra DetectorType = 375 + DetectorType_Audd DetectorType = 376 + DetectorType_Baremetrics DetectorType = 377 + DetectorType_Coinlib DetectorType = 378 + DetectorType_ExchangeRatesAPI DetectorType = 379 + DetectorType_CurrencyScoop DetectorType = 380 + DetectorType_FXMarket DetectorType = 381 + DetectorType_CurrencyCloud DetectorType = 382 + DetectorType_GetGeoAPI DetectorType = 383 + DetectorType_Abstract DetectorType = 384 + DetectorType_Billomat DetectorType = 385 + DetectorType_Dovico DetectorType = 386 + DetectorType_Bitbar DetectorType = 387 + DetectorType_Bugsnag DetectorType = 388 + DetectorType_AssemblyAI DetectorType = 389 + DetectorType_AdafruitIO DetectorType = 390 + DetectorType_Apify DetectorType = 391 + DetectorType_CoinGecko DetectorType = 392 + DetectorType_CryptoCompare DetectorType = 393 + DetectorType_Fullstory DetectorType = 394 + DetectorType_HelloSign DetectorType = 395 + DetectorType_Loyverse DetectorType = 396 + DetectorType_NetCore DetectorType = 397 + DetectorType_SauceLabs DetectorType = 398 + DetectorType_AlienVault DetectorType = 399 + DetectorType_Apiflash DetectorType = 401 + DetectorType_Coinlayer DetectorType = 402 + DetectorType_CurrentsAPI DetectorType = 403 + DetectorType_DataGov DetectorType = 404 + DetectorType_Enigma DetectorType = 405 + DetectorType_FinancialModelingPrep DetectorType = 406 + DetectorType_Geocodio DetectorType = 407 + DetectorType_HereAPI DetectorType = 408 + DetectorType_Macaddress DetectorType = 409 + DetectorType_OOPSpam DetectorType = 410 + DetectorType_ProtocolsIO DetectorType = 411 + DetectorType_ScraperAPI DetectorType = 412 + DetectorType_SecurityTrails DetectorType = 413 + DetectorType_TomorrowIO DetectorType = 414 + DetectorType_WorldCoinIndex DetectorType = 415 + DetectorType_FacePlusPlus DetectorType = 416 + DetectorType_Voicegain DetectorType = 417 + DetectorType_Deepgram DetectorType = 418 + DetectorType_VisualCrossing DetectorType = 419 + DetectorType_Finnhub DetectorType = 420 + DetectorType_Tiingo DetectorType = 421 + DetectorType_RingCentral DetectorType = 422 + DetectorType_Finage DetectorType = 423 + DetectorType_Edamam DetectorType = 424 + DetectorType_HypeAuditor DetectorType = 425 + DetectorType_Gengo DetectorType = 426 + DetectorType_Front DetectorType = 427 + DetectorType_Fleetbase DetectorType = 428 + DetectorType_Bubble DetectorType = 429 + DetectorType_Bannerbear DetectorType = 430 + DetectorType_Adzuna DetectorType = 431 + DetectorType_BitcoinAverage DetectorType = 432 + DetectorType_CommerceJS DetectorType = 433 + DetectorType_DetectLanguage DetectorType = 434 + DetectorType_FakeJSON DetectorType = 435 + DetectorType_Graphhopper DetectorType = 436 + DetectorType_Lexigram DetectorType = 437 + DetectorType_LinkPreview DetectorType = 438 + DetectorType_Numverify DetectorType = 439 + DetectorType_ProxyCrawl DetectorType = 440 + DetectorType_ZipCodeAPI DetectorType = 441 + DetectorType_Cometchat DetectorType = 442 + DetectorType_Keygen DetectorType = 443 + DetectorType_Mixcloud DetectorType = 444 + DetectorType_TatumIO DetectorType = 445 + DetectorType_Tmetric DetectorType = 446 + DetectorType_Lastfm DetectorType = 447 + DetectorType_Browshot DetectorType = 448 + DetectorType_JSONbin DetectorType = 449 + DetectorType_LocationIQ DetectorType = 450 + DetectorType_ScreenshotAPI DetectorType = 451 + DetectorType_WeatherStack DetectorType = 452 + DetectorType_Amadeus DetectorType = 453 + DetectorType_FourSquare DetectorType = 454 + DetectorType_Flickr DetectorType = 455 + DetectorType_ClickHelp DetectorType = 456 + DetectorType_Ambee DetectorType = 457 + DetectorType_Api2Cart DetectorType = 458 + DetectorType_Hypertrack DetectorType = 459 + DetectorType_KakaoTalk DetectorType = 460 + DetectorType_RiteKit DetectorType = 461 + DetectorType_Shutterstock DetectorType = 462 + DetectorType_Text2Data DetectorType = 463 + DetectorType_YouNeedABudget DetectorType = 464 + DetectorType_Cricket DetectorType = 465 + DetectorType_Filestack DetectorType = 466 + DetectorType_Gyazo DetectorType = 467 + DetectorType_Mavenlink DetectorType = 468 + DetectorType_Sheety DetectorType = 469 + DetectorType_Sportsmonk DetectorType = 470 + DetectorType_Stockdata DetectorType = 471 + DetectorType_Unsplash DetectorType = 472 + DetectorType_Allsports DetectorType = 473 + DetectorType_CalorieNinja DetectorType = 474 + DetectorType_WalkScore DetectorType = 475 + DetectorType_Strava DetectorType = 476 + DetectorType_Cicero DetectorType = 477 + DetectorType_IPQuality DetectorType = 478 + DetectorType_ParallelDots DetectorType = 479 + DetectorType_Roaring DetectorType = 480 + DetectorType_Mailsac DetectorType = 481 + DetectorType_Whoxy DetectorType = 482 + DetectorType_WorldWeather DetectorType = 483 + DetectorType_ApiFonica DetectorType = 484 + DetectorType_Aylien DetectorType = 485 + DetectorType_Geocode DetectorType = 486 + DetectorType_IconFinder DetectorType = 487 + DetectorType_Ipify DetectorType = 488 + DetectorType_LanguageLayer DetectorType = 489 + DetectorType_Lob DetectorType = 490 + DetectorType_OnWaterIO DetectorType = 491 + DetectorType_Pastebin DetectorType = 492 + DetectorType_PdfLayer DetectorType = 493 + DetectorType_Pixabay DetectorType = 494 + DetectorType_ReadMe DetectorType = 495 + DetectorType_VatLayer DetectorType = 496 + DetectorType_VirusTotal DetectorType = 497 + DetectorType_AirVisual DetectorType = 498 + DetectorType_Currencyfreaks DetectorType = 499 + DetectorType_Duffel DetectorType = 500 + DetectorType_FlatIO DetectorType = 501 + DetectorType_M3o DetectorType = 502 + DetectorType_Mesibo DetectorType = 503 + DetectorType_Openuv DetectorType = 504 + DetectorType_Snipcart DetectorType = 505 + DetectorType_Besttime DetectorType = 506 + DetectorType_Happyscribe DetectorType = 507 + DetectorType_Humanity DetectorType = 508 + DetectorType_Impala DetectorType = 509 + DetectorType_Loginradius DetectorType = 510 + DetectorType_AutoPilot DetectorType = 511 + DetectorType_Bitmex DetectorType = 512 + DetectorType_ClustDoc DetectorType = 513 + DetectorType_Messari DetectorType = 514 + DetectorType_PdfShift DetectorType = 515 + DetectorType_Poloniex DetectorType = 516 + DetectorType_RestpackHtmlToPdfAPI DetectorType = 517 + DetectorType_RestpackScreenshotAPI DetectorType = 518 + DetectorType_ShutterstockOAuth DetectorType = 519 + DetectorType_SkyBiometry DetectorType = 520 + DetectorType_AbuseIPDB DetectorType = 521 + DetectorType_AletheiaApi DetectorType = 522 + DetectorType_BlitApp DetectorType = 523 + DetectorType_Censys DetectorType = 524 + DetectorType_Cloverly DetectorType = 525 + DetectorType_CountryLayer DetectorType = 526 + DetectorType_FileIO DetectorType = 527 + DetectorType_FlightApi DetectorType = 528 + DetectorType_Geoapify DetectorType = 529 + DetectorType_IPinfoDB DetectorType = 530 + DetectorType_MediaStack DetectorType = 531 + DetectorType_NasdaqDataLink DetectorType = 532 + DetectorType_OpenCageData DetectorType = 533 + DetectorType_Paymongo DetectorType = 534 + DetectorType_PositionStack DetectorType = 535 + DetectorType_Rebrandly DetectorType = 536 + DetectorType_ScreenshotLayer DetectorType = 537 + DetectorType_Stytch DetectorType = 538 + DetectorType_Unplugg DetectorType = 539 + DetectorType_UPCDatabase DetectorType = 540 + DetectorType_UserStack DetectorType = 541 + DetectorType_Geocodify DetectorType = 542 + DetectorType_Newscatcher DetectorType = 543 + DetectorType_Nicereply DetectorType = 544 + DetectorType_Partnerstack DetectorType = 545 + DetectorType_Route4me DetectorType = 546 + DetectorType_Scrapeowl DetectorType = 547 + DetectorType_ScrapingDog DetectorType = 548 + DetectorType_Streak DetectorType = 549 + DetectorType_Veriphone DetectorType = 550 + DetectorType_Webscraping DetectorType = 551 + DetectorType_Zenscrape DetectorType = 552 + DetectorType_Zenserp DetectorType = 553 + DetectorType_CoinApi DetectorType = 554 + DetectorType_Gitter DetectorType = 555 + DetectorType_Host DetectorType = 556 + DetectorType_Iexcloud DetectorType = 557 + DetectorType_Restpack DetectorType = 558 + DetectorType_ScraperBox DetectorType = 559 + DetectorType_ScrapingAnt DetectorType = 560 + DetectorType_SerpStack DetectorType = 561 + DetectorType_SmartyStreets DetectorType = 562 + DetectorType_TicketMaster DetectorType = 563 + DetectorType_AviationStack DetectorType = 564 + DetectorType_BombBomb DetectorType = 565 + DetectorType_Commodities DetectorType = 566 + DetectorType_Dfuse DetectorType = 567 + DetectorType_EdenAI DetectorType = 568 + DetectorType_Glassnode DetectorType = 569 + DetectorType_Guru DetectorType = 570 + DetectorType_Hive DetectorType = 571 + DetectorType_Hiveage DetectorType = 572 + DetectorType_Kickbox DetectorType = 573 + DetectorType_Passbase DetectorType = 574 + DetectorType_PostageApp DetectorType = 575 + DetectorType_PureStake DetectorType = 576 + DetectorType_Qubole DetectorType = 577 + DetectorType_CarbonInterface DetectorType = 578 + DetectorType_Intrinio DetectorType = 579 + // Deprecated: Do not use. + DetectorType_QuickMetrics DetectorType = 580 + DetectorType_ScrapeStack DetectorType = 581 + DetectorType_TechnicalAnalysisApi DetectorType = 582 + DetectorType_Urlscan DetectorType = 583 + DetectorType_BaseApiIO DetectorType = 584 + DetectorType_DailyCO DetectorType = 585 + DetectorType_TLy DetectorType = 586 + DetectorType_Shortcut DetectorType = 587 + DetectorType_Appfollow DetectorType = 588 + DetectorType_Thinkific DetectorType = 589 + DetectorType_Feedly DetectorType = 590 + DetectorType_Stitchdata DetectorType = 591 + DetectorType_Fetchrss DetectorType = 592 + DetectorType_Signupgenius DetectorType = 593 + DetectorType_Signaturit DetectorType = 594 + DetectorType_Optimizely DetectorType = 595 + DetectorType_OcrSpace DetectorType = 596 + DetectorType_WeatherBit DetectorType = 597 + DetectorType_BuddyNS DetectorType = 598 + DetectorType_ZipAPI DetectorType = 599 + DetectorType_ZipBooks DetectorType = 600 + DetectorType_Onedesk DetectorType = 601 + DetectorType_Bugherd DetectorType = 602 + DetectorType_Blazemeter DetectorType = 603 + DetectorType_Autodesk DetectorType = 604 + DetectorType_Tru DetectorType = 605 + DetectorType_UnifyID DetectorType = 606 + DetectorType_Trimble DetectorType = 607 + DetectorType_Smooch DetectorType = 608 + DetectorType_Semaphore DetectorType = 609 + DetectorType_Telnyx DetectorType = 610 + DetectorType_Signalwire DetectorType = 611 + DetectorType_Textmagic DetectorType = 612 + DetectorType_Serphouse DetectorType = 613 + DetectorType_Planyo DetectorType = 614 + DetectorType_Simplybook DetectorType = 615 + DetectorType_Vyte DetectorType = 616 + DetectorType_Nylas DetectorType = 617 + DetectorType_Squareup DetectorType = 618 + DetectorType_Dandelion DetectorType = 619 + // Deprecated: Do not use. + DetectorType_DataFire DetectorType = 620 + DetectorType_DeepAI DetectorType = 621 + DetectorType_MeaningCloud DetectorType = 622 + DetectorType_NeutrinoApi DetectorType = 623 + DetectorType_Storecove DetectorType = 624 + DetectorType_Shipday DetectorType = 625 + DetectorType_Sentiment DetectorType = 626 + DetectorType_StreamChatMessaging DetectorType = 627 + DetectorType_TeamworkCRM DetectorType = 628 + DetectorType_TeamworkDesk DetectorType = 629 + DetectorType_TeamworkSpaces DetectorType = 630 + DetectorType_TheOddsApi DetectorType = 631 + DetectorType_Apacta DetectorType = 632 + DetectorType_GetSandbox DetectorType = 633 + // Deprecated: Do not use. + DetectorType_Happi DetectorType = 634 + DetectorType_Oanda DetectorType = 635 + DetectorType_FastForex DetectorType = 636 + DetectorType_APIMatic DetectorType = 637 + DetectorType_VersionEye DetectorType = 638 + DetectorType_EagleEyeNetworks DetectorType = 639 + DetectorType_ThousandEyes DetectorType = 640 + DetectorType_SelectPDF DetectorType = 641 + DetectorType_Flightstats DetectorType = 642 + DetectorType_ChecIO DetectorType = 643 + DetectorType_Manifest DetectorType = 644 + DetectorType_ApiScience DetectorType = 645 + DetectorType_AppSynergy DetectorType = 646 + DetectorType_Caflou DetectorType = 647 + DetectorType_Caspio DetectorType = 648 + DetectorType_ChecklyHQ DetectorType = 649 + DetectorType_CloudElements DetectorType = 650 + DetectorType_DronaHQ DetectorType = 651 + DetectorType_Enablex DetectorType = 652 + DetectorType_Fmfw DetectorType = 653 + DetectorType_GoodDay DetectorType = 654 + DetectorType_Luno DetectorType = 655 + DetectorType_Meistertask DetectorType = 656 + DetectorType_Mindmeister DetectorType = 657 + DetectorType_PeopleDataLabs DetectorType = 658 + DetectorType_ScraperSite DetectorType = 659 + DetectorType_Scrapfly DetectorType = 660 + DetectorType_SimplyNoted DetectorType = 661 + DetectorType_TravelPayouts DetectorType = 662 + DetectorType_WebScraper DetectorType = 663 + DetectorType_Convier DetectorType = 664 + DetectorType_Courier DetectorType = 665 + DetectorType_Ditto DetectorType = 666 + DetectorType_Findl DetectorType = 667 + DetectorType_Lendflow DetectorType = 668 + DetectorType_Moderation DetectorType = 669 + DetectorType_Opendatasoft DetectorType = 670 + DetectorType_Podio DetectorType = 671 + DetectorType_Rockset DetectorType = 672 + DetectorType_Rownd DetectorType = 673 + DetectorType_Shotstack DetectorType = 674 + DetectorType_Swiftype DetectorType = 675 + DetectorType_Twitter DetectorType = 676 + DetectorType_Honey DetectorType = 677 + DetectorType_Freshdesk DetectorType = 678 + DetectorType_Upwave DetectorType = 679 + DetectorType_Fountain DetectorType = 680 + DetectorType_Freshbooks DetectorType = 681 + DetectorType_Mite DetectorType = 682 + DetectorType_Deputy DetectorType = 683 + DetectorType_Beebole DetectorType = 684 + DetectorType_Cashboard DetectorType = 685 + DetectorType_Kanban DetectorType = 686 + DetectorType_Worksnaps DetectorType = 687 + DetectorType_MyIntervals DetectorType = 688 + DetectorType_InvoiceOcean DetectorType = 689 + DetectorType_Sherpadesk DetectorType = 690 + DetectorType_Mrticktock DetectorType = 691 + DetectorType_Chatfule DetectorType = 692 + DetectorType_Aeroworkflow DetectorType = 693 + DetectorType_Emailoctopus DetectorType = 694 + DetectorType_Fusebill DetectorType = 695 + DetectorType_Geckoboard DetectorType = 696 + DetectorType_Gosquared DetectorType = 697 + DetectorType_Moonclerk DetectorType = 698 + DetectorType_Paymoapp DetectorType = 699 + DetectorType_Mixmax DetectorType = 700 + DetectorType_Processst DetectorType = 701 + DetectorType_Repairshopr DetectorType = 702 + DetectorType_Goshippo DetectorType = 703 + DetectorType_Sigopt DetectorType = 704 + DetectorType_Sugester DetectorType = 705 + DetectorType_Viewneo DetectorType = 706 + DetectorType_BoostNote DetectorType = 707 + DetectorType_CaptainData DetectorType = 708 + DetectorType_Checkvist DetectorType = 709 + DetectorType_Cliengo DetectorType = 710 + DetectorType_Cloze DetectorType = 711 + DetectorType_FormIO DetectorType = 712 + DetectorType_FormBucket DetectorType = 713 + DetectorType_GoCanvas DetectorType = 714 + DetectorType_MadKudu DetectorType = 715 + DetectorType_NozbeTeams DetectorType = 716 + DetectorType_Papyrs DetectorType = 717 + DetectorType_SuperNotesAPI DetectorType = 718 + DetectorType_Tallyfy DetectorType = 719 + DetectorType_ZenkitAPI DetectorType = 720 + DetectorType_CloudImage DetectorType = 721 + DetectorType_UploadCare DetectorType = 722 + DetectorType_Borgbase DetectorType = 723 + DetectorType_Pipedream DetectorType = 724 + DetectorType_Sirv DetectorType = 725 + DetectorType_Diffbot DetectorType = 726 + DetectorType_EightxEight DetectorType = 727 + DetectorType_Sendoso DetectorType = 728 + DetectorType_Printfection DetectorType = 729 + DetectorType_Authorize DetectorType = 730 + DetectorType_PandaScore DetectorType = 731 + DetectorType_Paymo DetectorType = 732 + DetectorType_AvazaPersonalAccessToken DetectorType = 733 + DetectorType_PlanviewLeanKit DetectorType = 734 + DetectorType_Livestorm DetectorType = 735 + DetectorType_KuCoin DetectorType = 736 + DetectorType_MetaAPI DetectorType = 737 + DetectorType_NiceHash DetectorType = 738 + DetectorType_CexIO DetectorType = 739 + DetectorType_Klipfolio DetectorType = 740 + DetectorType_Dynatrace DetectorType = 741 + DetectorType_MollieAPIKey DetectorType = 742 + DetectorType_MollieAccessToken DetectorType = 743 + DetectorType_BasisTheory DetectorType = 744 + DetectorType_Nordigen DetectorType = 745 + DetectorType_FlagsmithEnvironmentKey DetectorType = 746 + DetectorType_FlagsmithToken DetectorType = 747 + DetectorType_Mux DetectorType = 748 + DetectorType_Column DetectorType = 749 + DetectorType_Sendbird DetectorType = 750 + DetectorType_SendbirdOrganizationAPI DetectorType = 751 + DetectorType_Midise DetectorType = 752 + DetectorType_Mockaroo DetectorType = 753 + DetectorType_Image4 DetectorType = 754 + DetectorType_Pinata DetectorType = 755 + DetectorType_BrowserStack DetectorType = 756 + DetectorType_CrossBrowserTesting DetectorType = 757 + DetectorType_Loadmill DetectorType = 758 + DetectorType_TestingBot DetectorType = 759 + DetectorType_KnapsackPro DetectorType = 760 + DetectorType_Qase DetectorType = 761 + DetectorType_Dareboost DetectorType = 762 + DetectorType_GTMetrix DetectorType = 763 + DetectorType_Holistic DetectorType = 764 + DetectorType_Parsers DetectorType = 765 + DetectorType_ScrutinizerCi DetectorType = 766 + DetectorType_SonarCloud DetectorType = 767 + DetectorType_APITemplate DetectorType = 768 + DetectorType_ConversionTools DetectorType = 769 + DetectorType_CraftMyPDF DetectorType = 770 + DetectorType_ExportSDK DetectorType = 771 + // Deprecated: Do not use. + DetectorType_GlitterlyAPI DetectorType = 772 + DetectorType_Hybiscus DetectorType = 773 + DetectorType_Miro DetectorType = 774 + DetectorType_Statuspage DetectorType = 775 + DetectorType_Statuspal DetectorType = 776 + DetectorType_Teletype DetectorType = 777 + DetectorType_TimeCamp DetectorType = 778 + DetectorType_Userflow DetectorType = 779 + DetectorType_Wistia DetectorType = 780 + DetectorType_SportRadar DetectorType = 781 + DetectorType_UptimeRobot DetectorType = 782 + DetectorType_Codequiry DetectorType = 783 + DetectorType_ExtractorAPI DetectorType = 784 + DetectorType_Signable DetectorType = 785 + DetectorType_MagicBell DetectorType = 786 + DetectorType_Stormboard DetectorType = 787 + DetectorType_Apilayer DetectorType = 788 + DetectorType_Disqus DetectorType = 789 + DetectorType_Woopra DetectorType = 790 + DetectorType_Paperform DetectorType = 791 + DetectorType_Gumroad DetectorType = 792 + DetectorType_Paydirtapp DetectorType = 793 + DetectorType_Detectify DetectorType = 794 + DetectorType_Statuscake DetectorType = 795 + DetectorType_Jumpseller DetectorType = 796 + DetectorType_LunchMoney DetectorType = 797 + DetectorType_Rosette DetectorType = 798 + DetectorType_Yelp DetectorType = 799 + DetectorType_Atera DetectorType = 800 + DetectorType_EcoStruxureIT DetectorType = 801 + DetectorType_Aha DetectorType = 802 + DetectorType_Parsehub DetectorType = 803 + DetectorType_PackageCloud DetectorType = 804 + DetectorType_Cloudsmith DetectorType = 805 + DetectorType_Flowdash DetectorType = 806 + // Deprecated: Do not use. + DetectorType_Flowdock DetectorType = 807 + DetectorType_Fibery DetectorType = 808 + DetectorType_Typetalk DetectorType = 809 + DetectorType_VoodooSMS DetectorType = 810 + DetectorType_ZulipChat DetectorType = 811 + DetectorType_Formcraft DetectorType = 812 + DetectorType_Iexapis DetectorType = 813 + DetectorType_Reachmail DetectorType = 814 + DetectorType_Chartmogul DetectorType = 815 + DetectorType_Appointedd DetectorType = 816 + DetectorType_Wit DetectorType = 817 + DetectorType_RechargePayments DetectorType = 818 + DetectorType_Diggernaut DetectorType = 819 + DetectorType_MonkeyLearn DetectorType = 820 + DetectorType_Duply DetectorType = 821 + DetectorType_Postbacks DetectorType = 822 + DetectorType_Collect2 DetectorType = 823 + DetectorType_ZenRows DetectorType = 824 + DetectorType_Zipcodebase DetectorType = 825 + DetectorType_Tefter DetectorType = 826 + DetectorType_Twist DetectorType = 827 + DetectorType_BraintreePayments DetectorType = 828 + DetectorType_CloudConvert DetectorType = 829 + DetectorType_Grafana DetectorType = 830 + DetectorType_ConvertApi DetectorType = 831 + DetectorType_Transferwise DetectorType = 832 + DetectorType_Bulksms DetectorType = 833 + DetectorType_Databox DetectorType = 834 + DetectorType_Onesignal DetectorType = 835 + DetectorType_Rentman DetectorType = 836 + DetectorType_Parseur DetectorType = 837 + DetectorType_Docparser DetectorType = 838 + DetectorType_Formsite DetectorType = 839 + DetectorType_Tickettailor DetectorType = 840 + DetectorType_Lemlist DetectorType = 841 + DetectorType_Prodpad DetectorType = 842 + DetectorType_Formstack DetectorType = 843 + DetectorType_Codeclimate DetectorType = 844 + DetectorType_Codemagic DetectorType = 845 + DetectorType_Vbout DetectorType = 846 + DetectorType_Nightfall DetectorType = 847 + DetectorType_FlightLabs DetectorType = 848 + DetectorType_SpeechTextAI DetectorType = 849 + DetectorType_PollsAPI DetectorType = 850 + DetectorType_SimFin DetectorType = 851 + DetectorType_Scalr DetectorType = 852 + DetectorType_Kanbantool DetectorType = 853 + DetectorType_Brightlocal DetectorType = 854 + DetectorType_Hotwire DetectorType = 855 + DetectorType_Instabot DetectorType = 856 + DetectorType_Timekit DetectorType = 857 + DetectorType_Interseller DetectorType = 858 + DetectorType_Mojohelpdesk DetectorType = 859 + DetectorType_Createsend DetectorType = 860 + DetectorType_Getresponse DetectorType = 861 + DetectorType_Dynadot DetectorType = 862 + DetectorType_Demio DetectorType = 863 + DetectorType_Tokeet DetectorType = 864 + DetectorType_Myexperiment DetectorType = 865 + DetectorType_Copyscape DetectorType = 866 + DetectorType_Besnappy DetectorType = 867 + DetectorType_Salesmate DetectorType = 868 + DetectorType_Heatmapapi DetectorType = 869 + DetectorType_Websitepulse DetectorType = 870 + DetectorType_Uclassify DetectorType = 871 + DetectorType_Convert DetectorType = 872 + DetectorType_PDFmyURL DetectorType = 873 + DetectorType_Api2Convert DetectorType = 874 + DetectorType_Opsgenie DetectorType = 875 + DetectorType_Gemini DetectorType = 876 + DetectorType_Honeycomb DetectorType = 877 + DetectorType_KalturaAppToken DetectorType = 878 + DetectorType_KalturaSession DetectorType = 879 + DetectorType_BitGo DetectorType = 880 + DetectorType_Optidash DetectorType = 881 + DetectorType_Imgix DetectorType = 882 + DetectorType_ImageToText DetectorType = 883 + DetectorType_Page2Images DetectorType = 884 + DetectorType_Quickbase DetectorType = 885 + DetectorType_Redbooth DetectorType = 886 + DetectorType_Nubela DetectorType = 887 + DetectorType_Infobip DetectorType = 888 + DetectorType_Uproc DetectorType = 889 + DetectorType_Supportbee DetectorType = 890 + DetectorType_Aftership DetectorType = 891 + DetectorType_Edusign DetectorType = 892 + DetectorType_Teamup DetectorType = 893 + DetectorType_Workday DetectorType = 894 + DetectorType_MongoDB DetectorType = 895 + DetectorType_NGC DetectorType = 896 + DetectorType_DigitalOceanV2 DetectorType = 897 + DetectorType_SQLServer DetectorType = 898 + DetectorType_FTP DetectorType = 899 + DetectorType_Redis DetectorType = 900 + DetectorType_LDAP DetectorType = 901 + DetectorType_Shopify DetectorType = 902 + DetectorType_RabbitMQ DetectorType = 903 + DetectorType_CustomRegex DetectorType = 904 + DetectorType_Etherscan DetectorType = 905 + DetectorType_Infura DetectorType = 906 + DetectorType_Alchemy DetectorType = 907 + DetectorType_BlockNative DetectorType = 908 + DetectorType_Moralis DetectorType = 909 + DetectorType_BscScan DetectorType = 910 + DetectorType_CoinMarketCap DetectorType = 911 + DetectorType_Percy DetectorType = 912 + DetectorType_TinesWebhook DetectorType = 913 + DetectorType_Pulumi DetectorType = 914 + DetectorType_SupabaseToken DetectorType = 915 + DetectorType_NuGetApiKey DetectorType = 916 + DetectorType_Aiven DetectorType = 917 + DetectorType_Prefect DetectorType = 918 + DetectorType_Docusign DetectorType = 919 + DetectorType_Couchbase DetectorType = 920 + DetectorType_Dockerhub DetectorType = 921 + DetectorType_TrufflehogEnterprise DetectorType = 922 + DetectorType_EnvoyApiKey DetectorType = 923 + DetectorType_GitHubOauth2 DetectorType = 924 + DetectorType_Salesforce DetectorType = 925 + DetectorType_HuggingFace DetectorType = 926 + DetectorType_Snowflake DetectorType = 927 + DetectorType_Sourcegraph DetectorType = 928 + DetectorType_Tailscale DetectorType = 929 + DetectorType_Web3Storage DetectorType = 930 + DetectorType_AzureStorage DetectorType = 931 + DetectorType_PlanetScaleDb DetectorType = 932 + DetectorType_Anthropic DetectorType = 933 + DetectorType_Ramp DetectorType = 934 + DetectorType_Klaviyo DetectorType = 935 + DetectorType_SourcegraphCody DetectorType = 936 + DetectorType_Voiceflow DetectorType = 937 + DetectorType_Privacy DetectorType = 938 + DetectorType_IPInfo DetectorType = 939 + DetectorType_Ip2location DetectorType = 940 + DetectorType_Instamojo DetectorType = 941 + DetectorType_Portainer DetectorType = 942 + DetectorType_PortainerToken DetectorType = 943 + DetectorType_Loggly DetectorType = 944 + DetectorType_OpenVpn DetectorType = 945 + DetectorType_VagrantCloudPersonalToken DetectorType = 946 ) // Enum value maps for DetectorType. @@ -1950,6 +1964,14 @@ var ( 936: "SourcegraphCody", 937: "Voiceflow", 938: "Privacy", + 939: "IPInfo", + 940: "Ip2location", + 941: "Instamojo", + 942: "Portainer", + 943: "PortainerToken", + 944: "Loggly", + 945: "OpenVpn", + 946: "VagrantCloudPersonalToken", } DetectorType_value = map[string]int32{ "Alibaba": 0, @@ -2887,6 +2909,14 @@ var ( "SourcegraphCody": 936, "Voiceflow": 937, "Privacy": 938, + "IPInfo": 939, + "Ip2location": 940, + "Instamojo": 941, + "Portainer": 942, + "PortainerToken": 943, + "Loggly": 944, + "OpenVpn": 945, + "VagrantCloudPersonalToken": 946, } ) @@ -3265,7 +3295,7 @@ var file_detectors_proto_rawDesc = []byte{ 0x44, 0x65, 0x63, 0x6f, 0x64, 0x65, 0x72, 0x54, 0x79, 0x70, 0x65, 0x12, 0x0b, 0x0a, 0x07, 0x55, 0x4e, 0x4b, 0x4e, 0x4f, 0x57, 0x4e, 0x10, 0x00, 0x12, 0x09, 0x0a, 0x05, 0x50, 0x4c, 0x41, 0x49, 0x4e, 0x10, 0x01, 0x12, 0x0a, 0x0a, 0x06, 0x42, 0x41, 0x53, 0x45, 0x36, 0x34, 0x10, 0x02, 0x12, - 0x09, 0x0a, 0x05, 0x55, 0x54, 0x46, 0x31, 0x36, 0x10, 0x03, 0x2a, 0xc4, 0x75, 0x0a, 0x0c, 0x44, + 0x09, 0x0a, 0x05, 0x55, 0x54, 0x46, 0x31, 0x36, 0x10, 0x03, 0x2a, 0xeb, 0x76, 0x0a, 0x0c, 0x44, 0x65, 0x74, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x54, 0x79, 0x70, 0x65, 0x12, 0x0b, 0x0a, 0x07, 0x41, 0x6c, 0x69, 0x62, 0x61, 0x62, 0x61, 0x10, 0x00, 0x12, 0x08, 0x0a, 0x04, 0x41, 0x4d, 0x51, 0x50, 0x10, 0x01, 0x12, 0x07, 0x0a, 0x03, 0x41, 0x57, 0x53, 0x10, 0x02, 0x12, 0x09, 0x0a, 0x05, 0x41, @@ -3624,287 +3654,288 @@ var file_detectors_proto_rawDesc = []byte{ 0x0a, 0x05, 0x49, 0x6d, 0x67, 0x75, 0x72, 0x10, 0xdc, 0x02, 0x12, 0x0b, 0x0a, 0x06, 0x49, 0x6d, 0x61, 0x67, 0x67, 0x61, 0x10, 0xdd, 0x02, 0x12, 0x0b, 0x0a, 0x06, 0x53, 0x4d, 0x53, 0x41, 0x70, 0x69, 0x10, 0xde, 0x02, 0x12, 0x11, 0x0a, 0x0c, 0x44, 0x69, 0x73, 0x74, 0x72, 0x69, 0x62, 0x75, - 0x73, 0x69, 0x6f, 0x6e, 0x10, 0xdf, 0x02, 0x12, 0x0e, 0x0a, 0x09, 0x42, 0x6c, 0x61, 0x62, 0x6c, - 0x61, 0x62, 0x75, 0x73, 0x10, 0xe0, 0x02, 0x12, 0x0d, 0x0a, 0x08, 0x57, 0x6f, 0x72, 0x64, 0x73, - 0x41, 0x70, 0x69, 0x10, 0xe1, 0x02, 0x12, 0x12, 0x0a, 0x0d, 0x43, 0x75, 0x72, 0x72, 0x65, 0x6e, - 0x63, 0x79, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x10, 0xe2, 0x02, 0x12, 0x0d, 0x0a, 0x08, 0x48, 0x74, - 0x6d, 0x6c, 0x32, 0x50, 0x64, 0x66, 0x10, 0xe3, 0x02, 0x12, 0x12, 0x0a, 0x0d, 0x49, 0x50, 0x47, - 0x65, 0x6f, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x10, 0xe4, 0x02, 0x12, 0x0b, 0x0a, - 0x06, 0x4f, 0x77, 0x6c, 0x62, 0x6f, 0x74, 0x10, 0xe5, 0x02, 0x12, 0x11, 0x0a, 0x0c, 0x43, 0x6c, - 0x6f, 0x75, 0x64, 0x6d, 0x65, 0x72, 0x73, 0x69, 0x76, 0x65, 0x10, 0xe6, 0x02, 0x12, 0x0d, 0x0a, - 0x08, 0x44, 0x79, 0x6e, 0x61, 0x6c, 0x69, 0x73, 0x74, 0x10, 0xe7, 0x02, 0x12, 0x14, 0x0a, 0x0f, - 0x45, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x52, 0x61, 0x74, 0x65, 0x41, 0x50, 0x49, 0x10, - 0xe8, 0x02, 0x12, 0x0f, 0x0a, 0x0a, 0x48, 0x6f, 0x6c, 0x69, 0x64, 0x61, 0x79, 0x41, 0x50, 0x49, - 0x10, 0xe9, 0x02, 0x12, 0x0a, 0x0a, 0x05, 0x49, 0x70, 0x61, 0x70, 0x69, 0x10, 0xea, 0x02, 0x12, - 0x10, 0x0a, 0x0b, 0x4d, 0x61, 0x72, 0x6b, 0x65, 0x74, 0x73, 0x74, 0x61, 0x63, 0x6b, 0x10, 0xeb, - 0x02, 0x12, 0x10, 0x0a, 0x0b, 0x4e, 0x75, 0x74, 0x72, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x69, 0x78, - 0x10, 0xec, 0x02, 0x12, 0x0a, 0x0a, 0x05, 0x53, 0x77, 0x65, 0x6c, 0x6c, 0x10, 0xed, 0x02, 0x12, - 0x19, 0x0a, 0x14, 0x43, 0x6c, 0x69, 0x63, 0x6b, 0x75, 0x70, 0x50, 0x65, 0x72, 0x73, 0x6f, 0x6e, - 0x61, 0x6c, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x10, 0xee, 0x02, 0x12, 0x0a, 0x0a, 0x05, 0x4e, 0x69, - 0x74, 0x72, 0x6f, 0x10, 0xef, 0x02, 0x12, 0x08, 0x0a, 0x03, 0x52, 0x65, 0x76, 0x10, 0xf0, 0x02, - 0x12, 0x0d, 0x0a, 0x08, 0x52, 0x75, 0x6e, 0x52, 0x75, 0x6e, 0x49, 0x74, 0x10, 0xf1, 0x02, 0x12, - 0x0d, 0x0a, 0x08, 0x54, 0x79, 0x70, 0x65, 0x66, 0x6f, 0x72, 0x6d, 0x10, 0xf2, 0x02, 0x12, 0x0d, - 0x0a, 0x08, 0x4d, 0x69, 0x78, 0x70, 0x61, 0x6e, 0x65, 0x6c, 0x10, 0xf3, 0x02, 0x12, 0x0c, 0x0a, - 0x07, 0x54, 0x72, 0x61, 0x64, 0x69, 0x65, 0x72, 0x10, 0xf4, 0x02, 0x12, 0x0d, 0x0a, 0x08, 0x56, - 0x65, 0x72, 0x69, 0x66, 0x69, 0x65, 0x72, 0x10, 0xf5, 0x02, 0x12, 0x0d, 0x0a, 0x08, 0x56, 0x6f, - 0x75, 0x63, 0x68, 0x65, 0x72, 0x79, 0x10, 0xf6, 0x02, 0x12, 0x0b, 0x0a, 0x06, 0x41, 0x6c, 0x65, - 0x67, 0x72, 0x61, 0x10, 0xf7, 0x02, 0x12, 0x09, 0x0a, 0x04, 0x41, 0x75, 0x64, 0x64, 0x10, 0xf8, - 0x02, 0x12, 0x10, 0x0a, 0x0b, 0x42, 0x61, 0x72, 0x65, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, - 0x10, 0xf9, 0x02, 0x12, 0x0c, 0x0a, 0x07, 0x43, 0x6f, 0x69, 0x6e, 0x6c, 0x69, 0x62, 0x10, 0xfa, - 0x02, 0x12, 0x15, 0x0a, 0x10, 0x45, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x52, 0x61, 0x74, - 0x65, 0x73, 0x41, 0x50, 0x49, 0x10, 0xfb, 0x02, 0x12, 0x12, 0x0a, 0x0d, 0x43, 0x75, 0x72, 0x72, - 0x65, 0x6e, 0x63, 0x79, 0x53, 0x63, 0x6f, 0x6f, 0x70, 0x10, 0xfc, 0x02, 0x12, 0x0d, 0x0a, 0x08, - 0x46, 0x58, 0x4d, 0x61, 0x72, 0x6b, 0x65, 0x74, 0x10, 0xfd, 0x02, 0x12, 0x12, 0x0a, 0x0d, 0x43, - 0x75, 0x72, 0x72, 0x65, 0x6e, 0x63, 0x79, 0x43, 0x6c, 0x6f, 0x75, 0x64, 0x10, 0xfe, 0x02, 0x12, - 0x0e, 0x0a, 0x09, 0x47, 0x65, 0x74, 0x47, 0x65, 0x6f, 0x41, 0x50, 0x49, 0x10, 0xff, 0x02, 0x12, - 0x0d, 0x0a, 0x08, 0x41, 0x62, 0x73, 0x74, 0x72, 0x61, 0x63, 0x74, 0x10, 0x80, 0x03, 0x12, 0x0d, - 0x0a, 0x08, 0x42, 0x69, 0x6c, 0x6c, 0x6f, 0x6d, 0x61, 0x74, 0x10, 0x81, 0x03, 0x12, 0x0b, 0x0a, - 0x06, 0x44, 0x6f, 0x76, 0x69, 0x63, 0x6f, 0x10, 0x82, 0x03, 0x12, 0x0b, 0x0a, 0x06, 0x42, 0x69, - 0x74, 0x62, 0x61, 0x72, 0x10, 0x83, 0x03, 0x12, 0x0c, 0x0a, 0x07, 0x42, 0x75, 0x67, 0x73, 0x6e, - 0x61, 0x67, 0x10, 0x84, 0x03, 0x12, 0x0f, 0x0a, 0x0a, 0x41, 0x73, 0x73, 0x65, 0x6d, 0x62, 0x6c, - 0x79, 0x41, 0x49, 0x10, 0x85, 0x03, 0x12, 0x0f, 0x0a, 0x0a, 0x41, 0x64, 0x61, 0x66, 0x72, 0x75, - 0x69, 0x74, 0x49, 0x4f, 0x10, 0x86, 0x03, 0x12, 0x0a, 0x0a, 0x05, 0x41, 0x70, 0x69, 0x66, 0x79, - 0x10, 0x87, 0x03, 0x12, 0x0e, 0x0a, 0x09, 0x43, 0x6f, 0x69, 0x6e, 0x47, 0x65, 0x63, 0x6b, 0x6f, - 0x10, 0x88, 0x03, 0x12, 0x12, 0x0a, 0x0d, 0x43, 0x72, 0x79, 0x70, 0x74, 0x6f, 0x43, 0x6f, 0x6d, - 0x70, 0x61, 0x72, 0x65, 0x10, 0x89, 0x03, 0x12, 0x0e, 0x0a, 0x09, 0x46, 0x75, 0x6c, 0x6c, 0x73, - 0x74, 0x6f, 0x72, 0x79, 0x10, 0x8a, 0x03, 0x12, 0x0e, 0x0a, 0x09, 0x48, 0x65, 0x6c, 0x6c, 0x6f, - 0x53, 0x69, 0x67, 0x6e, 0x10, 0x8b, 0x03, 0x12, 0x0d, 0x0a, 0x08, 0x4c, 0x6f, 0x79, 0x76, 0x65, - 0x72, 0x73, 0x65, 0x10, 0x8c, 0x03, 0x12, 0x0c, 0x0a, 0x07, 0x4e, 0x65, 0x74, 0x43, 0x6f, 0x72, - 0x65, 0x10, 0x8d, 0x03, 0x12, 0x0e, 0x0a, 0x09, 0x53, 0x61, 0x75, 0x63, 0x65, 0x4c, 0x61, 0x62, - 0x73, 0x10, 0x8e, 0x03, 0x12, 0x0f, 0x0a, 0x0a, 0x41, 0x6c, 0x69, 0x65, 0x6e, 0x56, 0x61, 0x75, - 0x6c, 0x74, 0x10, 0x8f, 0x03, 0x12, 0x0d, 0x0a, 0x08, 0x41, 0x70, 0x69, 0x66, 0x6c, 0x61, 0x73, - 0x68, 0x10, 0x91, 0x03, 0x12, 0x0e, 0x0a, 0x09, 0x43, 0x6f, 0x69, 0x6e, 0x6c, 0x61, 0x79, 0x65, - 0x72, 0x10, 0x92, 0x03, 0x12, 0x10, 0x0a, 0x0b, 0x43, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x73, - 0x41, 0x50, 0x49, 0x10, 0x93, 0x03, 0x12, 0x0c, 0x0a, 0x07, 0x44, 0x61, 0x74, 0x61, 0x47, 0x6f, - 0x76, 0x10, 0x94, 0x03, 0x12, 0x0b, 0x0a, 0x06, 0x45, 0x6e, 0x69, 0x67, 0x6d, 0x61, 0x10, 0x95, - 0x03, 0x12, 0x1a, 0x0a, 0x15, 0x46, 0x69, 0x6e, 0x61, 0x6e, 0x63, 0x69, 0x61, 0x6c, 0x4d, 0x6f, - 0x64, 0x65, 0x6c, 0x69, 0x6e, 0x67, 0x50, 0x72, 0x65, 0x70, 0x10, 0x96, 0x03, 0x12, 0x0d, 0x0a, - 0x08, 0x47, 0x65, 0x6f, 0x63, 0x6f, 0x64, 0x69, 0x6f, 0x10, 0x97, 0x03, 0x12, 0x0c, 0x0a, 0x07, - 0x48, 0x65, 0x72, 0x65, 0x41, 0x50, 0x49, 0x10, 0x98, 0x03, 0x12, 0x0f, 0x0a, 0x0a, 0x4d, 0x61, - 0x63, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x10, 0x99, 0x03, 0x12, 0x0c, 0x0a, 0x07, 0x4f, - 0x4f, 0x50, 0x53, 0x70, 0x61, 0x6d, 0x10, 0x9a, 0x03, 0x12, 0x10, 0x0a, 0x0b, 0x50, 0x72, 0x6f, - 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x73, 0x49, 0x4f, 0x10, 0x9b, 0x03, 0x12, 0x0f, 0x0a, 0x0a, 0x53, - 0x63, 0x72, 0x61, 0x70, 0x65, 0x72, 0x41, 0x50, 0x49, 0x10, 0x9c, 0x03, 0x12, 0x13, 0x0a, 0x0e, - 0x53, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x54, 0x72, 0x61, 0x69, 0x6c, 0x73, 0x10, 0x9d, - 0x03, 0x12, 0x0f, 0x0a, 0x0a, 0x54, 0x6f, 0x6d, 0x6f, 0x72, 0x72, 0x6f, 0x77, 0x49, 0x4f, 0x10, - 0x9e, 0x03, 0x12, 0x13, 0x0a, 0x0e, 0x57, 0x6f, 0x72, 0x6c, 0x64, 0x43, 0x6f, 0x69, 0x6e, 0x49, - 0x6e, 0x64, 0x65, 0x78, 0x10, 0x9f, 0x03, 0x12, 0x11, 0x0a, 0x0c, 0x46, 0x61, 0x63, 0x65, 0x50, - 0x6c, 0x75, 0x73, 0x50, 0x6c, 0x75, 0x73, 0x10, 0xa0, 0x03, 0x12, 0x0e, 0x0a, 0x09, 0x56, 0x6f, - 0x69, 0x63, 0x65, 0x67, 0x61, 0x69, 0x6e, 0x10, 0xa1, 0x03, 0x12, 0x0d, 0x0a, 0x08, 0x44, 0x65, - 0x65, 0x70, 0x67, 0x72, 0x61, 0x6d, 0x10, 0xa2, 0x03, 0x12, 0x13, 0x0a, 0x0e, 0x56, 0x69, 0x73, - 0x75, 0x61, 0x6c, 0x43, 0x72, 0x6f, 0x73, 0x73, 0x69, 0x6e, 0x67, 0x10, 0xa3, 0x03, 0x12, 0x0c, - 0x0a, 0x07, 0x46, 0x69, 0x6e, 0x6e, 0x68, 0x75, 0x62, 0x10, 0xa4, 0x03, 0x12, 0x0b, 0x0a, 0x06, - 0x54, 0x69, 0x69, 0x6e, 0x67, 0x6f, 0x10, 0xa5, 0x03, 0x12, 0x10, 0x0a, 0x0b, 0x52, 0x69, 0x6e, - 0x67, 0x43, 0x65, 0x6e, 0x74, 0x72, 0x61, 0x6c, 0x10, 0xa6, 0x03, 0x12, 0x0b, 0x0a, 0x06, 0x46, - 0x69, 0x6e, 0x61, 0x67, 0x65, 0x10, 0xa7, 0x03, 0x12, 0x0b, 0x0a, 0x06, 0x45, 0x64, 0x61, 0x6d, - 0x61, 0x6d, 0x10, 0xa8, 0x03, 0x12, 0x10, 0x0a, 0x0b, 0x48, 0x79, 0x70, 0x65, 0x41, 0x75, 0x64, - 0x69, 0x74, 0x6f, 0x72, 0x10, 0xa9, 0x03, 0x12, 0x0a, 0x0a, 0x05, 0x47, 0x65, 0x6e, 0x67, 0x6f, - 0x10, 0xaa, 0x03, 0x12, 0x0a, 0x0a, 0x05, 0x46, 0x72, 0x6f, 0x6e, 0x74, 0x10, 0xab, 0x03, 0x12, - 0x0e, 0x0a, 0x09, 0x46, 0x6c, 0x65, 0x65, 0x74, 0x62, 0x61, 0x73, 0x65, 0x10, 0xac, 0x03, 0x12, - 0x0b, 0x0a, 0x06, 0x42, 0x75, 0x62, 0x62, 0x6c, 0x65, 0x10, 0xad, 0x03, 0x12, 0x0f, 0x0a, 0x0a, - 0x42, 0x61, 0x6e, 0x6e, 0x65, 0x72, 0x62, 0x65, 0x61, 0x72, 0x10, 0xae, 0x03, 0x12, 0x0b, 0x0a, - 0x06, 0x41, 0x64, 0x7a, 0x75, 0x6e, 0x61, 0x10, 0xaf, 0x03, 0x12, 0x13, 0x0a, 0x0e, 0x42, 0x69, - 0x74, 0x63, 0x6f, 0x69, 0x6e, 0x41, 0x76, 0x65, 0x72, 0x61, 0x67, 0x65, 0x10, 0xb0, 0x03, 0x12, - 0x0f, 0x0a, 0x0a, 0x43, 0x6f, 0x6d, 0x6d, 0x65, 0x72, 0x63, 0x65, 0x4a, 0x53, 0x10, 0xb1, 0x03, - 0x12, 0x13, 0x0a, 0x0e, 0x44, 0x65, 0x74, 0x65, 0x63, 0x74, 0x4c, 0x61, 0x6e, 0x67, 0x75, 0x61, - 0x67, 0x65, 0x10, 0xb2, 0x03, 0x12, 0x0d, 0x0a, 0x08, 0x46, 0x61, 0x6b, 0x65, 0x4a, 0x53, 0x4f, - 0x4e, 0x10, 0xb3, 0x03, 0x12, 0x10, 0x0a, 0x0b, 0x47, 0x72, 0x61, 0x70, 0x68, 0x68, 0x6f, 0x70, - 0x70, 0x65, 0x72, 0x10, 0xb4, 0x03, 0x12, 0x0d, 0x0a, 0x08, 0x4c, 0x65, 0x78, 0x69, 0x67, 0x72, - 0x61, 0x6d, 0x10, 0xb5, 0x03, 0x12, 0x10, 0x0a, 0x0b, 0x4c, 0x69, 0x6e, 0x6b, 0x50, 0x72, 0x65, - 0x76, 0x69, 0x65, 0x77, 0x10, 0xb6, 0x03, 0x12, 0x0e, 0x0a, 0x09, 0x4e, 0x75, 0x6d, 0x76, 0x65, - 0x72, 0x69, 0x66, 0x79, 0x10, 0xb7, 0x03, 0x12, 0x0f, 0x0a, 0x0a, 0x50, 0x72, 0x6f, 0x78, 0x79, - 0x43, 0x72, 0x61, 0x77, 0x6c, 0x10, 0xb8, 0x03, 0x12, 0x0f, 0x0a, 0x0a, 0x5a, 0x69, 0x70, 0x43, - 0x6f, 0x64, 0x65, 0x41, 0x50, 0x49, 0x10, 0xb9, 0x03, 0x12, 0x0e, 0x0a, 0x09, 0x43, 0x6f, 0x6d, - 0x65, 0x74, 0x63, 0x68, 0x61, 0x74, 0x10, 0xba, 0x03, 0x12, 0x0b, 0x0a, 0x06, 0x4b, 0x65, 0x79, - 0x67, 0x65, 0x6e, 0x10, 0xbb, 0x03, 0x12, 0x0d, 0x0a, 0x08, 0x4d, 0x69, 0x78, 0x63, 0x6c, 0x6f, - 0x75, 0x64, 0x10, 0xbc, 0x03, 0x12, 0x0c, 0x0a, 0x07, 0x54, 0x61, 0x74, 0x75, 0x6d, 0x49, 0x4f, - 0x10, 0xbd, 0x03, 0x12, 0x0c, 0x0a, 0x07, 0x54, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x10, 0xbe, - 0x03, 0x12, 0x0b, 0x0a, 0x06, 0x4c, 0x61, 0x73, 0x74, 0x66, 0x6d, 0x10, 0xbf, 0x03, 0x12, 0x0d, - 0x0a, 0x08, 0x42, 0x72, 0x6f, 0x77, 0x73, 0x68, 0x6f, 0x74, 0x10, 0xc0, 0x03, 0x12, 0x0c, 0x0a, - 0x07, 0x4a, 0x53, 0x4f, 0x4e, 0x62, 0x69, 0x6e, 0x10, 0xc1, 0x03, 0x12, 0x0f, 0x0a, 0x0a, 0x4c, - 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x51, 0x10, 0xc2, 0x03, 0x12, 0x12, 0x0a, 0x0d, - 0x53, 0x63, 0x72, 0x65, 0x65, 0x6e, 0x73, 0x68, 0x6f, 0x74, 0x41, 0x50, 0x49, 0x10, 0xc3, 0x03, - 0x12, 0x11, 0x0a, 0x0c, 0x57, 0x65, 0x61, 0x74, 0x68, 0x65, 0x72, 0x53, 0x74, 0x61, 0x63, 0x6b, - 0x10, 0xc4, 0x03, 0x12, 0x0c, 0x0a, 0x07, 0x41, 0x6d, 0x61, 0x64, 0x65, 0x75, 0x73, 0x10, 0xc5, - 0x03, 0x12, 0x0f, 0x0a, 0x0a, 0x46, 0x6f, 0x75, 0x72, 0x53, 0x71, 0x75, 0x61, 0x72, 0x65, 0x10, - 0xc6, 0x03, 0x12, 0x0b, 0x0a, 0x06, 0x46, 0x6c, 0x69, 0x63, 0x6b, 0x72, 0x10, 0xc7, 0x03, 0x12, - 0x0e, 0x0a, 0x09, 0x43, 0x6c, 0x69, 0x63, 0x6b, 0x48, 0x65, 0x6c, 0x70, 0x10, 0xc8, 0x03, 0x12, - 0x0a, 0x0a, 0x05, 0x41, 0x6d, 0x62, 0x65, 0x65, 0x10, 0xc9, 0x03, 0x12, 0x0d, 0x0a, 0x08, 0x41, - 0x70, 0x69, 0x32, 0x43, 0x61, 0x72, 0x74, 0x10, 0xca, 0x03, 0x12, 0x0f, 0x0a, 0x0a, 0x48, 0x79, - 0x70, 0x65, 0x72, 0x74, 0x72, 0x61, 0x63, 0x6b, 0x10, 0xcb, 0x03, 0x12, 0x0e, 0x0a, 0x09, 0x4b, - 0x61, 0x6b, 0x61, 0x6f, 0x54, 0x61, 0x6c, 0x6b, 0x10, 0xcc, 0x03, 0x12, 0x0c, 0x0a, 0x07, 0x52, - 0x69, 0x74, 0x65, 0x4b, 0x69, 0x74, 0x10, 0xcd, 0x03, 0x12, 0x11, 0x0a, 0x0c, 0x53, 0x68, 0x75, - 0x74, 0x74, 0x65, 0x72, 0x73, 0x74, 0x6f, 0x63, 0x6b, 0x10, 0xce, 0x03, 0x12, 0x0e, 0x0a, 0x09, - 0x54, 0x65, 0x78, 0x74, 0x32, 0x44, 0x61, 0x74, 0x61, 0x10, 0xcf, 0x03, 0x12, 0x13, 0x0a, 0x0e, - 0x59, 0x6f, 0x75, 0x4e, 0x65, 0x65, 0x64, 0x41, 0x42, 0x75, 0x64, 0x67, 0x65, 0x74, 0x10, 0xd0, - 0x03, 0x12, 0x0c, 0x0a, 0x07, 0x43, 0x72, 0x69, 0x63, 0x6b, 0x65, 0x74, 0x10, 0xd1, 0x03, 0x12, - 0x0e, 0x0a, 0x09, 0x46, 0x69, 0x6c, 0x65, 0x73, 0x74, 0x61, 0x63, 0x6b, 0x10, 0xd2, 0x03, 0x12, - 0x0a, 0x0a, 0x05, 0x47, 0x79, 0x61, 0x7a, 0x6f, 0x10, 0xd3, 0x03, 0x12, 0x0e, 0x0a, 0x09, 0x4d, - 0x61, 0x76, 0x65, 0x6e, 0x6c, 0x69, 0x6e, 0x6b, 0x10, 0xd4, 0x03, 0x12, 0x0b, 0x0a, 0x06, 0x53, - 0x68, 0x65, 0x65, 0x74, 0x79, 0x10, 0xd5, 0x03, 0x12, 0x0f, 0x0a, 0x0a, 0x53, 0x70, 0x6f, 0x72, - 0x74, 0x73, 0x6d, 0x6f, 0x6e, 0x6b, 0x10, 0xd6, 0x03, 0x12, 0x0e, 0x0a, 0x09, 0x53, 0x74, 0x6f, - 0x63, 0x6b, 0x64, 0x61, 0x74, 0x61, 0x10, 0xd7, 0x03, 0x12, 0x0d, 0x0a, 0x08, 0x55, 0x6e, 0x73, - 0x70, 0x6c, 0x61, 0x73, 0x68, 0x10, 0xd8, 0x03, 0x12, 0x0e, 0x0a, 0x09, 0x41, 0x6c, 0x6c, 0x73, - 0x70, 0x6f, 0x72, 0x74, 0x73, 0x10, 0xd9, 0x03, 0x12, 0x11, 0x0a, 0x0c, 0x43, 0x61, 0x6c, 0x6f, - 0x72, 0x69, 0x65, 0x4e, 0x69, 0x6e, 0x6a, 0x61, 0x10, 0xda, 0x03, 0x12, 0x0e, 0x0a, 0x09, 0x57, - 0x61, 0x6c, 0x6b, 0x53, 0x63, 0x6f, 0x72, 0x65, 0x10, 0xdb, 0x03, 0x12, 0x0b, 0x0a, 0x06, 0x53, - 0x74, 0x72, 0x61, 0x76, 0x61, 0x10, 0xdc, 0x03, 0x12, 0x0b, 0x0a, 0x06, 0x43, 0x69, 0x63, 0x65, - 0x72, 0x6f, 0x10, 0xdd, 0x03, 0x12, 0x0e, 0x0a, 0x09, 0x49, 0x50, 0x51, 0x75, 0x61, 0x6c, 0x69, - 0x74, 0x79, 0x10, 0xde, 0x03, 0x12, 0x11, 0x0a, 0x0c, 0x50, 0x61, 0x72, 0x61, 0x6c, 0x6c, 0x65, - 0x6c, 0x44, 0x6f, 0x74, 0x73, 0x10, 0xdf, 0x03, 0x12, 0x0c, 0x0a, 0x07, 0x52, 0x6f, 0x61, 0x72, - 0x69, 0x6e, 0x67, 0x10, 0xe0, 0x03, 0x12, 0x0c, 0x0a, 0x07, 0x4d, 0x61, 0x69, 0x6c, 0x73, 0x61, - 0x63, 0x10, 0xe1, 0x03, 0x12, 0x0a, 0x0a, 0x05, 0x57, 0x68, 0x6f, 0x78, 0x79, 0x10, 0xe2, 0x03, - 0x12, 0x11, 0x0a, 0x0c, 0x57, 0x6f, 0x72, 0x6c, 0x64, 0x57, 0x65, 0x61, 0x74, 0x68, 0x65, 0x72, - 0x10, 0xe3, 0x03, 0x12, 0x0e, 0x0a, 0x09, 0x41, 0x70, 0x69, 0x46, 0x6f, 0x6e, 0x69, 0x63, 0x61, - 0x10, 0xe4, 0x03, 0x12, 0x0b, 0x0a, 0x06, 0x41, 0x79, 0x6c, 0x69, 0x65, 0x6e, 0x10, 0xe5, 0x03, - 0x12, 0x0c, 0x0a, 0x07, 0x47, 0x65, 0x6f, 0x63, 0x6f, 0x64, 0x65, 0x10, 0xe6, 0x03, 0x12, 0x0f, - 0x0a, 0x0a, 0x49, 0x63, 0x6f, 0x6e, 0x46, 0x69, 0x6e, 0x64, 0x65, 0x72, 0x10, 0xe7, 0x03, 0x12, - 0x0a, 0x0a, 0x05, 0x49, 0x70, 0x69, 0x66, 0x79, 0x10, 0xe8, 0x03, 0x12, 0x12, 0x0a, 0x0d, 0x4c, - 0x61, 0x6e, 0x67, 0x75, 0x61, 0x67, 0x65, 0x4c, 0x61, 0x79, 0x65, 0x72, 0x10, 0xe9, 0x03, 0x12, - 0x08, 0x0a, 0x03, 0x4c, 0x6f, 0x62, 0x10, 0xea, 0x03, 0x12, 0x0e, 0x0a, 0x09, 0x4f, 0x6e, 0x57, - 0x61, 0x74, 0x65, 0x72, 0x49, 0x4f, 0x10, 0xeb, 0x03, 0x12, 0x0d, 0x0a, 0x08, 0x50, 0x61, 0x73, - 0x74, 0x65, 0x62, 0x69, 0x6e, 0x10, 0xec, 0x03, 0x12, 0x0d, 0x0a, 0x08, 0x50, 0x64, 0x66, 0x4c, - 0x61, 0x79, 0x65, 0x72, 0x10, 0xed, 0x03, 0x12, 0x0c, 0x0a, 0x07, 0x50, 0x69, 0x78, 0x61, 0x62, - 0x61, 0x79, 0x10, 0xee, 0x03, 0x12, 0x0b, 0x0a, 0x06, 0x52, 0x65, 0x61, 0x64, 0x4d, 0x65, 0x10, - 0xef, 0x03, 0x12, 0x0d, 0x0a, 0x08, 0x56, 0x61, 0x74, 0x4c, 0x61, 0x79, 0x65, 0x72, 0x10, 0xf0, - 0x03, 0x12, 0x0f, 0x0a, 0x0a, 0x56, 0x69, 0x72, 0x75, 0x73, 0x54, 0x6f, 0x74, 0x61, 0x6c, 0x10, - 0xf1, 0x03, 0x12, 0x0e, 0x0a, 0x09, 0x41, 0x69, 0x72, 0x56, 0x69, 0x73, 0x75, 0x61, 0x6c, 0x10, - 0xf2, 0x03, 0x12, 0x13, 0x0a, 0x0e, 0x43, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x63, 0x79, 0x66, 0x72, - 0x65, 0x61, 0x6b, 0x73, 0x10, 0xf3, 0x03, 0x12, 0x0b, 0x0a, 0x06, 0x44, 0x75, 0x66, 0x66, 0x65, - 0x6c, 0x10, 0xf4, 0x03, 0x12, 0x0b, 0x0a, 0x06, 0x46, 0x6c, 0x61, 0x74, 0x49, 0x4f, 0x10, 0xf5, - 0x03, 0x12, 0x08, 0x0a, 0x03, 0x4d, 0x33, 0x6f, 0x10, 0xf6, 0x03, 0x12, 0x0b, 0x0a, 0x06, 0x4d, - 0x65, 0x73, 0x69, 0x62, 0x6f, 0x10, 0xf7, 0x03, 0x12, 0x0b, 0x0a, 0x06, 0x4f, 0x70, 0x65, 0x6e, - 0x75, 0x76, 0x10, 0xf8, 0x03, 0x12, 0x0d, 0x0a, 0x08, 0x53, 0x6e, 0x69, 0x70, 0x63, 0x61, 0x72, - 0x74, 0x10, 0xf9, 0x03, 0x12, 0x0d, 0x0a, 0x08, 0x42, 0x65, 0x73, 0x74, 0x74, 0x69, 0x6d, 0x65, - 0x10, 0xfa, 0x03, 0x12, 0x10, 0x0a, 0x0b, 0x48, 0x61, 0x70, 0x70, 0x79, 0x73, 0x63, 0x72, 0x69, - 0x62, 0x65, 0x10, 0xfb, 0x03, 0x12, 0x0d, 0x0a, 0x08, 0x48, 0x75, 0x6d, 0x61, 0x6e, 0x69, 0x74, - 0x79, 0x10, 0xfc, 0x03, 0x12, 0x0b, 0x0a, 0x06, 0x49, 0x6d, 0x70, 0x61, 0x6c, 0x61, 0x10, 0xfd, - 0x03, 0x12, 0x10, 0x0a, 0x0b, 0x4c, 0x6f, 0x67, 0x69, 0x6e, 0x72, 0x61, 0x64, 0x69, 0x75, 0x73, - 0x10, 0xfe, 0x03, 0x12, 0x0e, 0x0a, 0x09, 0x41, 0x75, 0x74, 0x6f, 0x50, 0x69, 0x6c, 0x6f, 0x74, - 0x10, 0xff, 0x03, 0x12, 0x0b, 0x0a, 0x06, 0x42, 0x69, 0x74, 0x6d, 0x65, 0x78, 0x10, 0x80, 0x04, - 0x12, 0x0d, 0x0a, 0x08, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x44, 0x6f, 0x63, 0x10, 0x81, 0x04, 0x12, - 0x0c, 0x0a, 0x07, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x72, 0x69, 0x10, 0x82, 0x04, 0x12, 0x0d, 0x0a, - 0x08, 0x50, 0x64, 0x66, 0x53, 0x68, 0x69, 0x66, 0x74, 0x10, 0x83, 0x04, 0x12, 0x0d, 0x0a, 0x08, - 0x50, 0x6f, 0x6c, 0x6f, 0x6e, 0x69, 0x65, 0x78, 0x10, 0x84, 0x04, 0x12, 0x19, 0x0a, 0x14, 0x52, - 0x65, 0x73, 0x74, 0x70, 0x61, 0x63, 0x6b, 0x48, 0x74, 0x6d, 0x6c, 0x54, 0x6f, 0x50, 0x64, 0x66, - 0x41, 0x50, 0x49, 0x10, 0x85, 0x04, 0x12, 0x1a, 0x0a, 0x15, 0x52, 0x65, 0x73, 0x74, 0x70, 0x61, - 0x63, 0x6b, 0x53, 0x63, 0x72, 0x65, 0x65, 0x6e, 0x73, 0x68, 0x6f, 0x74, 0x41, 0x50, 0x49, 0x10, - 0x86, 0x04, 0x12, 0x16, 0x0a, 0x11, 0x53, 0x68, 0x75, 0x74, 0x74, 0x65, 0x72, 0x73, 0x74, 0x6f, - 0x63, 0x6b, 0x4f, 0x41, 0x75, 0x74, 0x68, 0x10, 0x87, 0x04, 0x12, 0x10, 0x0a, 0x0b, 0x53, 0x6b, - 0x79, 0x42, 0x69, 0x6f, 0x6d, 0x65, 0x74, 0x72, 0x79, 0x10, 0x88, 0x04, 0x12, 0x0e, 0x0a, 0x09, - 0x41, 0x62, 0x75, 0x73, 0x65, 0x49, 0x50, 0x44, 0x42, 0x10, 0x89, 0x04, 0x12, 0x10, 0x0a, 0x0b, - 0x41, 0x6c, 0x65, 0x74, 0x68, 0x65, 0x69, 0x61, 0x41, 0x70, 0x69, 0x10, 0x8a, 0x04, 0x12, 0x0c, - 0x0a, 0x07, 0x42, 0x6c, 0x69, 0x74, 0x41, 0x70, 0x70, 0x10, 0x8b, 0x04, 0x12, 0x0b, 0x0a, 0x06, - 0x43, 0x65, 0x6e, 0x73, 0x79, 0x73, 0x10, 0x8c, 0x04, 0x12, 0x0d, 0x0a, 0x08, 0x43, 0x6c, 0x6f, - 0x76, 0x65, 0x72, 0x6c, 0x79, 0x10, 0x8d, 0x04, 0x12, 0x11, 0x0a, 0x0c, 0x43, 0x6f, 0x75, 0x6e, - 0x74, 0x72, 0x79, 0x4c, 0x61, 0x79, 0x65, 0x72, 0x10, 0x8e, 0x04, 0x12, 0x0b, 0x0a, 0x06, 0x46, - 0x69, 0x6c, 0x65, 0x49, 0x4f, 0x10, 0x8f, 0x04, 0x12, 0x0e, 0x0a, 0x09, 0x46, 0x6c, 0x69, 0x67, - 0x68, 0x74, 0x41, 0x70, 0x69, 0x10, 0x90, 0x04, 0x12, 0x0d, 0x0a, 0x08, 0x47, 0x65, 0x6f, 0x61, - 0x70, 0x69, 0x66, 0x79, 0x10, 0x91, 0x04, 0x12, 0x0d, 0x0a, 0x08, 0x49, 0x50, 0x69, 0x6e, 0x66, - 0x6f, 0x44, 0x42, 0x10, 0x92, 0x04, 0x12, 0x0f, 0x0a, 0x0a, 0x4d, 0x65, 0x64, 0x69, 0x61, 0x53, - 0x74, 0x61, 0x63, 0x6b, 0x10, 0x93, 0x04, 0x12, 0x13, 0x0a, 0x0e, 0x4e, 0x61, 0x73, 0x64, 0x61, - 0x71, 0x44, 0x61, 0x74, 0x61, 0x4c, 0x69, 0x6e, 0x6b, 0x10, 0x94, 0x04, 0x12, 0x11, 0x0a, 0x0c, - 0x4f, 0x70, 0x65, 0x6e, 0x43, 0x61, 0x67, 0x65, 0x44, 0x61, 0x74, 0x61, 0x10, 0x95, 0x04, 0x12, - 0x0d, 0x0a, 0x08, 0x50, 0x61, 0x79, 0x6d, 0x6f, 0x6e, 0x67, 0x6f, 0x10, 0x96, 0x04, 0x12, 0x12, - 0x0a, 0x0d, 0x50, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x63, 0x6b, 0x10, - 0x97, 0x04, 0x12, 0x0e, 0x0a, 0x09, 0x52, 0x65, 0x62, 0x72, 0x61, 0x6e, 0x64, 0x6c, 0x79, 0x10, - 0x98, 0x04, 0x12, 0x14, 0x0a, 0x0f, 0x53, 0x63, 0x72, 0x65, 0x65, 0x6e, 0x73, 0x68, 0x6f, 0x74, - 0x4c, 0x61, 0x79, 0x65, 0x72, 0x10, 0x99, 0x04, 0x12, 0x0b, 0x0a, 0x06, 0x53, 0x74, 0x79, 0x74, - 0x63, 0x68, 0x10, 0x9a, 0x04, 0x12, 0x0c, 0x0a, 0x07, 0x55, 0x6e, 0x70, 0x6c, 0x75, 0x67, 0x67, - 0x10, 0x9b, 0x04, 0x12, 0x10, 0x0a, 0x0b, 0x55, 0x50, 0x43, 0x44, 0x61, 0x74, 0x61, 0x62, 0x61, - 0x73, 0x65, 0x10, 0x9c, 0x04, 0x12, 0x0e, 0x0a, 0x09, 0x55, 0x73, 0x65, 0x72, 0x53, 0x74, 0x61, - 0x63, 0x6b, 0x10, 0x9d, 0x04, 0x12, 0x0e, 0x0a, 0x09, 0x47, 0x65, 0x6f, 0x63, 0x6f, 0x64, 0x69, - 0x66, 0x79, 0x10, 0x9e, 0x04, 0x12, 0x10, 0x0a, 0x0b, 0x4e, 0x65, 0x77, 0x73, 0x63, 0x61, 0x74, - 0x63, 0x68, 0x65, 0x72, 0x10, 0x9f, 0x04, 0x12, 0x0e, 0x0a, 0x09, 0x4e, 0x69, 0x63, 0x65, 0x72, - 0x65, 0x70, 0x6c, 0x79, 0x10, 0xa0, 0x04, 0x12, 0x11, 0x0a, 0x0c, 0x50, 0x61, 0x72, 0x74, 0x6e, - 0x65, 0x72, 0x73, 0x74, 0x61, 0x63, 0x6b, 0x10, 0xa1, 0x04, 0x12, 0x0d, 0x0a, 0x08, 0x52, 0x6f, - 0x75, 0x74, 0x65, 0x34, 0x6d, 0x65, 0x10, 0xa2, 0x04, 0x12, 0x0e, 0x0a, 0x09, 0x53, 0x63, 0x72, - 0x61, 0x70, 0x65, 0x6f, 0x77, 0x6c, 0x10, 0xa3, 0x04, 0x12, 0x10, 0x0a, 0x0b, 0x53, 0x63, 0x72, - 0x61, 0x70, 0x69, 0x6e, 0x67, 0x44, 0x6f, 0x67, 0x10, 0xa4, 0x04, 0x12, 0x0b, 0x0a, 0x06, 0x53, - 0x74, 0x72, 0x65, 0x61, 0x6b, 0x10, 0xa5, 0x04, 0x12, 0x0e, 0x0a, 0x09, 0x56, 0x65, 0x72, 0x69, - 0x70, 0x68, 0x6f, 0x6e, 0x65, 0x10, 0xa6, 0x04, 0x12, 0x10, 0x0a, 0x0b, 0x57, 0x65, 0x62, 0x73, - 0x63, 0x72, 0x61, 0x70, 0x69, 0x6e, 0x67, 0x10, 0xa7, 0x04, 0x12, 0x0e, 0x0a, 0x09, 0x5a, 0x65, - 0x6e, 0x73, 0x63, 0x72, 0x61, 0x70, 0x65, 0x10, 0xa8, 0x04, 0x12, 0x0c, 0x0a, 0x07, 0x5a, 0x65, - 0x6e, 0x73, 0x65, 0x72, 0x70, 0x10, 0xa9, 0x04, 0x12, 0x0c, 0x0a, 0x07, 0x43, 0x6f, 0x69, 0x6e, - 0x41, 0x70, 0x69, 0x10, 0xaa, 0x04, 0x12, 0x0b, 0x0a, 0x06, 0x47, 0x69, 0x74, 0x74, 0x65, 0x72, - 0x10, 0xab, 0x04, 0x12, 0x09, 0x0a, 0x04, 0x48, 0x6f, 0x73, 0x74, 0x10, 0xac, 0x04, 0x12, 0x0d, - 0x0a, 0x08, 0x49, 0x65, 0x78, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x10, 0xad, 0x04, 0x12, 0x0d, 0x0a, - 0x08, 0x52, 0x65, 0x73, 0x74, 0x70, 0x61, 0x63, 0x6b, 0x10, 0xae, 0x04, 0x12, 0x0f, 0x0a, 0x0a, - 0x53, 0x63, 0x72, 0x61, 0x70, 0x65, 0x72, 0x42, 0x6f, 0x78, 0x10, 0xaf, 0x04, 0x12, 0x10, 0x0a, - 0x0b, 0x53, 0x63, 0x72, 0x61, 0x70, 0x69, 0x6e, 0x67, 0x41, 0x6e, 0x74, 0x10, 0xb0, 0x04, 0x12, - 0x0e, 0x0a, 0x09, 0x53, 0x65, 0x72, 0x70, 0x53, 0x74, 0x61, 0x63, 0x6b, 0x10, 0xb1, 0x04, 0x12, - 0x12, 0x0a, 0x0d, 0x53, 0x6d, 0x61, 0x72, 0x74, 0x79, 0x53, 0x74, 0x72, 0x65, 0x65, 0x74, 0x73, - 0x10, 0xb2, 0x04, 0x12, 0x11, 0x0a, 0x0c, 0x54, 0x69, 0x63, 0x6b, 0x65, 0x74, 0x4d, 0x61, 0x73, - 0x74, 0x65, 0x72, 0x10, 0xb3, 0x04, 0x12, 0x12, 0x0a, 0x0d, 0x41, 0x76, 0x69, 0x61, 0x74, 0x69, - 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x63, 0x6b, 0x10, 0xb4, 0x04, 0x12, 0x0d, 0x0a, 0x08, 0x42, 0x6f, - 0x6d, 0x62, 0x42, 0x6f, 0x6d, 0x62, 0x10, 0xb5, 0x04, 0x12, 0x10, 0x0a, 0x0b, 0x43, 0x6f, 0x6d, - 0x6d, 0x6f, 0x64, 0x69, 0x74, 0x69, 0x65, 0x73, 0x10, 0xb6, 0x04, 0x12, 0x0a, 0x0a, 0x05, 0x44, - 0x66, 0x75, 0x73, 0x65, 0x10, 0xb7, 0x04, 0x12, 0x0b, 0x0a, 0x06, 0x45, 0x64, 0x65, 0x6e, 0x41, - 0x49, 0x10, 0xb8, 0x04, 0x12, 0x0e, 0x0a, 0x09, 0x47, 0x6c, 0x61, 0x73, 0x73, 0x6e, 0x6f, 0x64, - 0x65, 0x10, 0xb9, 0x04, 0x12, 0x09, 0x0a, 0x04, 0x47, 0x75, 0x72, 0x75, 0x10, 0xba, 0x04, 0x12, - 0x09, 0x0a, 0x04, 0x48, 0x69, 0x76, 0x65, 0x10, 0xbb, 0x04, 0x12, 0x0c, 0x0a, 0x07, 0x48, 0x69, - 0x76, 0x65, 0x61, 0x67, 0x65, 0x10, 0xbc, 0x04, 0x12, 0x0c, 0x0a, 0x07, 0x4b, 0x69, 0x63, 0x6b, - 0x62, 0x6f, 0x78, 0x10, 0xbd, 0x04, 0x12, 0x0d, 0x0a, 0x08, 0x50, 0x61, 0x73, 0x73, 0x62, 0x61, - 0x73, 0x65, 0x10, 0xbe, 0x04, 0x12, 0x0f, 0x0a, 0x0a, 0x50, 0x6f, 0x73, 0x74, 0x61, 0x67, 0x65, - 0x41, 0x70, 0x70, 0x10, 0xbf, 0x04, 0x12, 0x0e, 0x0a, 0x09, 0x50, 0x75, 0x72, 0x65, 0x53, 0x74, - 0x61, 0x6b, 0x65, 0x10, 0xc0, 0x04, 0x12, 0x0b, 0x0a, 0x06, 0x51, 0x75, 0x62, 0x6f, 0x6c, 0x65, - 0x10, 0xc1, 0x04, 0x12, 0x14, 0x0a, 0x0f, 0x43, 0x61, 0x72, 0x62, 0x6f, 0x6e, 0x49, 0x6e, 0x74, - 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, 0x10, 0xc2, 0x04, 0x12, 0x0d, 0x0a, 0x08, 0x49, 0x6e, 0x74, - 0x72, 0x69, 0x6e, 0x69, 0x6f, 0x10, 0xc3, 0x04, 0x12, 0x11, 0x0a, 0x0c, 0x51, 0x75, 0x69, 0x63, - 0x6b, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x10, 0xc4, 0x04, 0x12, 0x10, 0x0a, 0x0b, 0x53, - 0x63, 0x72, 0x61, 0x70, 0x65, 0x53, 0x74, 0x61, 0x63, 0x6b, 0x10, 0xc5, 0x04, 0x12, 0x19, 0x0a, - 0x14, 0x54, 0x65, 0x63, 0x68, 0x6e, 0x69, 0x63, 0x61, 0x6c, 0x41, 0x6e, 0x61, 0x6c, 0x79, 0x73, - 0x69, 0x73, 0x41, 0x70, 0x69, 0x10, 0xc6, 0x04, 0x12, 0x0c, 0x0a, 0x07, 0x55, 0x72, 0x6c, 0x73, - 0x63, 0x61, 0x6e, 0x10, 0xc7, 0x04, 0x12, 0x0e, 0x0a, 0x09, 0x42, 0x61, 0x73, 0x65, 0x41, 0x70, - 0x69, 0x49, 0x4f, 0x10, 0xc8, 0x04, 0x12, 0x0c, 0x0a, 0x07, 0x44, 0x61, 0x69, 0x6c, 0x79, 0x43, - 0x4f, 0x10, 0xc9, 0x04, 0x12, 0x08, 0x0a, 0x03, 0x54, 0x4c, 0x79, 0x10, 0xca, 0x04, 0x12, 0x0d, - 0x0a, 0x08, 0x53, 0x68, 0x6f, 0x72, 0x74, 0x63, 0x75, 0x74, 0x10, 0xcb, 0x04, 0x12, 0x0e, 0x0a, - 0x09, 0x41, 0x70, 0x70, 0x66, 0x6f, 0x6c, 0x6c, 0x6f, 0x77, 0x10, 0xcc, 0x04, 0x12, 0x0e, 0x0a, - 0x09, 0x54, 0x68, 0x69, 0x6e, 0x6b, 0x69, 0x66, 0x69, 0x63, 0x10, 0xcd, 0x04, 0x12, 0x0b, 0x0a, - 0x06, 0x46, 0x65, 0x65, 0x64, 0x6c, 0x79, 0x10, 0xce, 0x04, 0x12, 0x0f, 0x0a, 0x0a, 0x53, 0x74, - 0x69, 0x74, 0x63, 0x68, 0x64, 0x61, 0x74, 0x61, 0x10, 0xcf, 0x04, 0x12, 0x0d, 0x0a, 0x08, 0x46, - 0x65, 0x74, 0x63, 0x68, 0x72, 0x73, 0x73, 0x10, 0xd0, 0x04, 0x12, 0x11, 0x0a, 0x0c, 0x53, 0x69, - 0x67, 0x6e, 0x75, 0x70, 0x67, 0x65, 0x6e, 0x69, 0x75, 0x73, 0x10, 0xd1, 0x04, 0x12, 0x0f, 0x0a, - 0x0a, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x69, 0x74, 0x10, 0xd2, 0x04, 0x12, 0x0f, - 0x0a, 0x0a, 0x4f, 0x70, 0x74, 0x69, 0x6d, 0x69, 0x7a, 0x65, 0x6c, 0x79, 0x10, 0xd3, 0x04, 0x12, - 0x0d, 0x0a, 0x08, 0x4f, 0x63, 0x72, 0x53, 0x70, 0x61, 0x63, 0x65, 0x10, 0xd4, 0x04, 0x12, 0x0f, - 0x0a, 0x0a, 0x57, 0x65, 0x61, 0x74, 0x68, 0x65, 0x72, 0x42, 0x69, 0x74, 0x10, 0xd5, 0x04, 0x12, - 0x0c, 0x0a, 0x07, 0x42, 0x75, 0x64, 0x64, 0x79, 0x4e, 0x53, 0x10, 0xd6, 0x04, 0x12, 0x0b, 0x0a, - 0x06, 0x5a, 0x69, 0x70, 0x41, 0x50, 0x49, 0x10, 0xd7, 0x04, 0x12, 0x0d, 0x0a, 0x08, 0x5a, 0x69, - 0x70, 0x42, 0x6f, 0x6f, 0x6b, 0x73, 0x10, 0xd8, 0x04, 0x12, 0x0c, 0x0a, 0x07, 0x4f, 0x6e, 0x65, - 0x64, 0x65, 0x73, 0x6b, 0x10, 0xd9, 0x04, 0x12, 0x0c, 0x0a, 0x07, 0x42, 0x75, 0x67, 0x68, 0x65, - 0x72, 0x64, 0x10, 0xda, 0x04, 0x12, 0x0f, 0x0a, 0x0a, 0x42, 0x6c, 0x61, 0x7a, 0x65, 0x6d, 0x65, - 0x74, 0x65, 0x72, 0x10, 0xdb, 0x04, 0x12, 0x0d, 0x0a, 0x08, 0x41, 0x75, 0x74, 0x6f, 0x64, 0x65, - 0x73, 0x6b, 0x10, 0xdc, 0x04, 0x12, 0x08, 0x0a, 0x03, 0x54, 0x72, 0x75, 0x10, 0xdd, 0x04, 0x12, - 0x0c, 0x0a, 0x07, 0x55, 0x6e, 0x69, 0x66, 0x79, 0x49, 0x44, 0x10, 0xde, 0x04, 0x12, 0x0c, 0x0a, - 0x07, 0x54, 0x72, 0x69, 0x6d, 0x62, 0x6c, 0x65, 0x10, 0xdf, 0x04, 0x12, 0x0b, 0x0a, 0x06, 0x53, - 0x6d, 0x6f, 0x6f, 0x63, 0x68, 0x10, 0xe0, 0x04, 0x12, 0x0e, 0x0a, 0x09, 0x53, 0x65, 0x6d, 0x61, - 0x70, 0x68, 0x6f, 0x72, 0x65, 0x10, 0xe1, 0x04, 0x12, 0x0b, 0x0a, 0x06, 0x54, 0x65, 0x6c, 0x6e, - 0x79, 0x78, 0x10, 0xe2, 0x04, 0x12, 0x0f, 0x0a, 0x0a, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x6c, 0x77, - 0x69, 0x72, 0x65, 0x10, 0xe3, 0x04, 0x12, 0x0e, 0x0a, 0x09, 0x54, 0x65, 0x78, 0x74, 0x6d, 0x61, - 0x67, 0x69, 0x63, 0x10, 0xe4, 0x04, 0x12, 0x0e, 0x0a, 0x09, 0x53, 0x65, 0x72, 0x70, 0x68, 0x6f, - 0x75, 0x73, 0x65, 0x10, 0xe5, 0x04, 0x12, 0x0b, 0x0a, 0x06, 0x50, 0x6c, 0x61, 0x6e, 0x79, 0x6f, - 0x10, 0xe6, 0x04, 0x12, 0x0f, 0x0a, 0x0a, 0x53, 0x69, 0x6d, 0x70, 0x6c, 0x79, 0x62, 0x6f, 0x6f, - 0x6b, 0x10, 0xe7, 0x04, 0x12, 0x09, 0x0a, 0x04, 0x56, 0x79, 0x74, 0x65, 0x10, 0xe8, 0x04, 0x12, - 0x0a, 0x0a, 0x05, 0x4e, 0x79, 0x6c, 0x61, 0x73, 0x10, 0xe9, 0x04, 0x12, 0x0d, 0x0a, 0x08, 0x53, - 0x71, 0x75, 0x61, 0x72, 0x65, 0x75, 0x70, 0x10, 0xea, 0x04, 0x12, 0x0e, 0x0a, 0x09, 0x44, 0x61, - 0x6e, 0x64, 0x65, 0x6c, 0x69, 0x6f, 0x6e, 0x10, 0xeb, 0x04, 0x12, 0x0d, 0x0a, 0x08, 0x44, 0x61, - 0x74, 0x61, 0x46, 0x69, 0x72, 0x65, 0x10, 0xec, 0x04, 0x12, 0x0b, 0x0a, 0x06, 0x44, 0x65, 0x65, - 0x70, 0x41, 0x49, 0x10, 0xed, 0x04, 0x12, 0x11, 0x0a, 0x0c, 0x4d, 0x65, 0x61, 0x6e, 0x69, 0x6e, - 0x67, 0x43, 0x6c, 0x6f, 0x75, 0x64, 0x10, 0xee, 0x04, 0x12, 0x10, 0x0a, 0x0b, 0x4e, 0x65, 0x75, - 0x74, 0x72, 0x69, 0x6e, 0x6f, 0x41, 0x70, 0x69, 0x10, 0xef, 0x04, 0x12, 0x0e, 0x0a, 0x09, 0x53, - 0x74, 0x6f, 0x72, 0x65, 0x63, 0x6f, 0x76, 0x65, 0x10, 0xf0, 0x04, 0x12, 0x0c, 0x0a, 0x07, 0x53, - 0x68, 0x69, 0x70, 0x64, 0x61, 0x79, 0x10, 0xf1, 0x04, 0x12, 0x0e, 0x0a, 0x09, 0x53, 0x65, 0x6e, - 0x74, 0x69, 0x6d, 0x65, 0x6e, 0x74, 0x10, 0xf2, 0x04, 0x12, 0x18, 0x0a, 0x13, 0x53, 0x74, 0x72, - 0x65, 0x61, 0x6d, 0x43, 0x68, 0x61, 0x74, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x69, 0x6e, 0x67, - 0x10, 0xf3, 0x04, 0x12, 0x10, 0x0a, 0x0b, 0x54, 0x65, 0x61, 0x6d, 0x77, 0x6f, 0x72, 0x6b, 0x43, - 0x52, 0x4d, 0x10, 0xf4, 0x04, 0x12, 0x11, 0x0a, 0x0c, 0x54, 0x65, 0x61, 0x6d, 0x77, 0x6f, 0x72, - 0x6b, 0x44, 0x65, 0x73, 0x6b, 0x10, 0xf5, 0x04, 0x12, 0x13, 0x0a, 0x0e, 0x54, 0x65, 0x61, 0x6d, - 0x77, 0x6f, 0x72, 0x6b, 0x53, 0x70, 0x61, 0x63, 0x65, 0x73, 0x10, 0xf6, 0x04, 0x12, 0x0f, 0x0a, - 0x0a, 0x54, 0x68, 0x65, 0x4f, 0x64, 0x64, 0x73, 0x41, 0x70, 0x69, 0x10, 0xf7, 0x04, 0x12, 0x0b, - 0x0a, 0x06, 0x41, 0x70, 0x61, 0x63, 0x74, 0x61, 0x10, 0xf8, 0x04, 0x12, 0x0f, 0x0a, 0x0a, 0x47, - 0x65, 0x74, 0x53, 0x61, 0x6e, 0x64, 0x62, 0x6f, 0x78, 0x10, 0xf9, 0x04, 0x12, 0x0a, 0x0a, 0x05, - 0x48, 0x61, 0x70, 0x70, 0x69, 0x10, 0xfa, 0x04, 0x12, 0x0a, 0x0a, 0x05, 0x4f, 0x61, 0x6e, 0x64, + 0x73, 0x69, 0x6f, 0x6e, 0x10, 0xdf, 0x02, 0x12, 0x12, 0x0a, 0x09, 0x42, 0x6c, 0x61, 0x62, 0x6c, + 0x61, 0x62, 0x75, 0x73, 0x10, 0xe0, 0x02, 0x1a, 0x02, 0x08, 0x01, 0x12, 0x0d, 0x0a, 0x08, 0x57, + 0x6f, 0x72, 0x64, 0x73, 0x41, 0x70, 0x69, 0x10, 0xe1, 0x02, 0x12, 0x12, 0x0a, 0x0d, 0x43, 0x75, + 0x72, 0x72, 0x65, 0x6e, 0x63, 0x79, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x10, 0xe2, 0x02, 0x12, 0x0d, + 0x0a, 0x08, 0x48, 0x74, 0x6d, 0x6c, 0x32, 0x50, 0x64, 0x66, 0x10, 0xe3, 0x02, 0x12, 0x12, 0x0a, + 0x0d, 0x49, 0x50, 0x47, 0x65, 0x6f, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x10, 0xe4, + 0x02, 0x12, 0x0b, 0x0a, 0x06, 0x4f, 0x77, 0x6c, 0x62, 0x6f, 0x74, 0x10, 0xe5, 0x02, 0x12, 0x11, + 0x0a, 0x0c, 0x43, 0x6c, 0x6f, 0x75, 0x64, 0x6d, 0x65, 0x72, 0x73, 0x69, 0x76, 0x65, 0x10, 0xe6, + 0x02, 0x12, 0x0d, 0x0a, 0x08, 0x44, 0x79, 0x6e, 0x61, 0x6c, 0x69, 0x73, 0x74, 0x10, 0xe7, 0x02, + 0x12, 0x14, 0x0a, 0x0f, 0x45, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x52, 0x61, 0x74, 0x65, + 0x41, 0x50, 0x49, 0x10, 0xe8, 0x02, 0x12, 0x0f, 0x0a, 0x0a, 0x48, 0x6f, 0x6c, 0x69, 0x64, 0x61, + 0x79, 0x41, 0x50, 0x49, 0x10, 0xe9, 0x02, 0x12, 0x0a, 0x0a, 0x05, 0x49, 0x70, 0x61, 0x70, 0x69, + 0x10, 0xea, 0x02, 0x12, 0x10, 0x0a, 0x0b, 0x4d, 0x61, 0x72, 0x6b, 0x65, 0x74, 0x73, 0x74, 0x61, + 0x63, 0x6b, 0x10, 0xeb, 0x02, 0x12, 0x10, 0x0a, 0x0b, 0x4e, 0x75, 0x74, 0x72, 0x69, 0x74, 0x69, + 0x6f, 0x6e, 0x69, 0x78, 0x10, 0xec, 0x02, 0x12, 0x0a, 0x0a, 0x05, 0x53, 0x77, 0x65, 0x6c, 0x6c, + 0x10, 0xed, 0x02, 0x12, 0x19, 0x0a, 0x14, 0x43, 0x6c, 0x69, 0x63, 0x6b, 0x75, 0x70, 0x50, 0x65, + 0x72, 0x73, 0x6f, 0x6e, 0x61, 0x6c, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x10, 0xee, 0x02, 0x12, 0x0a, + 0x0a, 0x05, 0x4e, 0x69, 0x74, 0x72, 0x6f, 0x10, 0xef, 0x02, 0x12, 0x08, 0x0a, 0x03, 0x52, 0x65, + 0x76, 0x10, 0xf0, 0x02, 0x12, 0x0d, 0x0a, 0x08, 0x52, 0x75, 0x6e, 0x52, 0x75, 0x6e, 0x49, 0x74, + 0x10, 0xf1, 0x02, 0x12, 0x0d, 0x0a, 0x08, 0x54, 0x79, 0x70, 0x65, 0x66, 0x6f, 0x72, 0x6d, 0x10, + 0xf2, 0x02, 0x12, 0x0d, 0x0a, 0x08, 0x4d, 0x69, 0x78, 0x70, 0x61, 0x6e, 0x65, 0x6c, 0x10, 0xf3, + 0x02, 0x12, 0x0c, 0x0a, 0x07, 0x54, 0x72, 0x61, 0x64, 0x69, 0x65, 0x72, 0x10, 0xf4, 0x02, 0x12, + 0x0d, 0x0a, 0x08, 0x56, 0x65, 0x72, 0x69, 0x66, 0x69, 0x65, 0x72, 0x10, 0xf5, 0x02, 0x12, 0x0d, + 0x0a, 0x08, 0x56, 0x6f, 0x75, 0x63, 0x68, 0x65, 0x72, 0x79, 0x10, 0xf6, 0x02, 0x12, 0x0b, 0x0a, + 0x06, 0x41, 0x6c, 0x65, 0x67, 0x72, 0x61, 0x10, 0xf7, 0x02, 0x12, 0x09, 0x0a, 0x04, 0x41, 0x75, + 0x64, 0x64, 0x10, 0xf8, 0x02, 0x12, 0x10, 0x0a, 0x0b, 0x42, 0x61, 0x72, 0x65, 0x6d, 0x65, 0x74, + 0x72, 0x69, 0x63, 0x73, 0x10, 0xf9, 0x02, 0x12, 0x0c, 0x0a, 0x07, 0x43, 0x6f, 0x69, 0x6e, 0x6c, + 0x69, 0x62, 0x10, 0xfa, 0x02, 0x12, 0x15, 0x0a, 0x10, 0x45, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, + 0x65, 0x52, 0x61, 0x74, 0x65, 0x73, 0x41, 0x50, 0x49, 0x10, 0xfb, 0x02, 0x12, 0x12, 0x0a, 0x0d, + 0x43, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x63, 0x79, 0x53, 0x63, 0x6f, 0x6f, 0x70, 0x10, 0xfc, 0x02, + 0x12, 0x0d, 0x0a, 0x08, 0x46, 0x58, 0x4d, 0x61, 0x72, 0x6b, 0x65, 0x74, 0x10, 0xfd, 0x02, 0x12, + 0x12, 0x0a, 0x0d, 0x43, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x63, 0x79, 0x43, 0x6c, 0x6f, 0x75, 0x64, + 0x10, 0xfe, 0x02, 0x12, 0x0e, 0x0a, 0x09, 0x47, 0x65, 0x74, 0x47, 0x65, 0x6f, 0x41, 0x50, 0x49, + 0x10, 0xff, 0x02, 0x12, 0x0d, 0x0a, 0x08, 0x41, 0x62, 0x73, 0x74, 0x72, 0x61, 0x63, 0x74, 0x10, + 0x80, 0x03, 0x12, 0x0d, 0x0a, 0x08, 0x42, 0x69, 0x6c, 0x6c, 0x6f, 0x6d, 0x61, 0x74, 0x10, 0x81, + 0x03, 0x12, 0x0b, 0x0a, 0x06, 0x44, 0x6f, 0x76, 0x69, 0x63, 0x6f, 0x10, 0x82, 0x03, 0x12, 0x0b, + 0x0a, 0x06, 0x42, 0x69, 0x74, 0x62, 0x61, 0x72, 0x10, 0x83, 0x03, 0x12, 0x0c, 0x0a, 0x07, 0x42, + 0x75, 0x67, 0x73, 0x6e, 0x61, 0x67, 0x10, 0x84, 0x03, 0x12, 0x0f, 0x0a, 0x0a, 0x41, 0x73, 0x73, + 0x65, 0x6d, 0x62, 0x6c, 0x79, 0x41, 0x49, 0x10, 0x85, 0x03, 0x12, 0x0f, 0x0a, 0x0a, 0x41, 0x64, + 0x61, 0x66, 0x72, 0x75, 0x69, 0x74, 0x49, 0x4f, 0x10, 0x86, 0x03, 0x12, 0x0a, 0x0a, 0x05, 0x41, + 0x70, 0x69, 0x66, 0x79, 0x10, 0x87, 0x03, 0x12, 0x0e, 0x0a, 0x09, 0x43, 0x6f, 0x69, 0x6e, 0x47, + 0x65, 0x63, 0x6b, 0x6f, 0x10, 0x88, 0x03, 0x12, 0x12, 0x0a, 0x0d, 0x43, 0x72, 0x79, 0x70, 0x74, + 0x6f, 0x43, 0x6f, 0x6d, 0x70, 0x61, 0x72, 0x65, 0x10, 0x89, 0x03, 0x12, 0x0e, 0x0a, 0x09, 0x46, + 0x75, 0x6c, 0x6c, 0x73, 0x74, 0x6f, 0x72, 0x79, 0x10, 0x8a, 0x03, 0x12, 0x0e, 0x0a, 0x09, 0x48, + 0x65, 0x6c, 0x6c, 0x6f, 0x53, 0x69, 0x67, 0x6e, 0x10, 0x8b, 0x03, 0x12, 0x0d, 0x0a, 0x08, 0x4c, + 0x6f, 0x79, 0x76, 0x65, 0x72, 0x73, 0x65, 0x10, 0x8c, 0x03, 0x12, 0x0c, 0x0a, 0x07, 0x4e, 0x65, + 0x74, 0x43, 0x6f, 0x72, 0x65, 0x10, 0x8d, 0x03, 0x12, 0x0e, 0x0a, 0x09, 0x53, 0x61, 0x75, 0x63, + 0x65, 0x4c, 0x61, 0x62, 0x73, 0x10, 0x8e, 0x03, 0x12, 0x0f, 0x0a, 0x0a, 0x41, 0x6c, 0x69, 0x65, + 0x6e, 0x56, 0x61, 0x75, 0x6c, 0x74, 0x10, 0x8f, 0x03, 0x12, 0x0d, 0x0a, 0x08, 0x41, 0x70, 0x69, + 0x66, 0x6c, 0x61, 0x73, 0x68, 0x10, 0x91, 0x03, 0x12, 0x0e, 0x0a, 0x09, 0x43, 0x6f, 0x69, 0x6e, + 0x6c, 0x61, 0x79, 0x65, 0x72, 0x10, 0x92, 0x03, 0x12, 0x10, 0x0a, 0x0b, 0x43, 0x75, 0x72, 0x72, + 0x65, 0x6e, 0x74, 0x73, 0x41, 0x50, 0x49, 0x10, 0x93, 0x03, 0x12, 0x0c, 0x0a, 0x07, 0x44, 0x61, + 0x74, 0x61, 0x47, 0x6f, 0x76, 0x10, 0x94, 0x03, 0x12, 0x0b, 0x0a, 0x06, 0x45, 0x6e, 0x69, 0x67, + 0x6d, 0x61, 0x10, 0x95, 0x03, 0x12, 0x1a, 0x0a, 0x15, 0x46, 0x69, 0x6e, 0x61, 0x6e, 0x63, 0x69, + 0x61, 0x6c, 0x4d, 0x6f, 0x64, 0x65, 0x6c, 0x69, 0x6e, 0x67, 0x50, 0x72, 0x65, 0x70, 0x10, 0x96, + 0x03, 0x12, 0x0d, 0x0a, 0x08, 0x47, 0x65, 0x6f, 0x63, 0x6f, 0x64, 0x69, 0x6f, 0x10, 0x97, 0x03, + 0x12, 0x0c, 0x0a, 0x07, 0x48, 0x65, 0x72, 0x65, 0x41, 0x50, 0x49, 0x10, 0x98, 0x03, 0x12, 0x0f, + 0x0a, 0x0a, 0x4d, 0x61, 0x63, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x10, 0x99, 0x03, 0x12, + 0x0c, 0x0a, 0x07, 0x4f, 0x4f, 0x50, 0x53, 0x70, 0x61, 0x6d, 0x10, 0x9a, 0x03, 0x12, 0x10, 0x0a, + 0x0b, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x73, 0x49, 0x4f, 0x10, 0x9b, 0x03, 0x12, + 0x0f, 0x0a, 0x0a, 0x53, 0x63, 0x72, 0x61, 0x70, 0x65, 0x72, 0x41, 0x50, 0x49, 0x10, 0x9c, 0x03, + 0x12, 0x13, 0x0a, 0x0e, 0x53, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x54, 0x72, 0x61, 0x69, + 0x6c, 0x73, 0x10, 0x9d, 0x03, 0x12, 0x0f, 0x0a, 0x0a, 0x54, 0x6f, 0x6d, 0x6f, 0x72, 0x72, 0x6f, + 0x77, 0x49, 0x4f, 0x10, 0x9e, 0x03, 0x12, 0x13, 0x0a, 0x0e, 0x57, 0x6f, 0x72, 0x6c, 0x64, 0x43, + 0x6f, 0x69, 0x6e, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x10, 0x9f, 0x03, 0x12, 0x11, 0x0a, 0x0c, 0x46, + 0x61, 0x63, 0x65, 0x50, 0x6c, 0x75, 0x73, 0x50, 0x6c, 0x75, 0x73, 0x10, 0xa0, 0x03, 0x12, 0x0e, + 0x0a, 0x09, 0x56, 0x6f, 0x69, 0x63, 0x65, 0x67, 0x61, 0x69, 0x6e, 0x10, 0xa1, 0x03, 0x12, 0x0d, + 0x0a, 0x08, 0x44, 0x65, 0x65, 0x70, 0x67, 0x72, 0x61, 0x6d, 0x10, 0xa2, 0x03, 0x12, 0x13, 0x0a, + 0x0e, 0x56, 0x69, 0x73, 0x75, 0x61, 0x6c, 0x43, 0x72, 0x6f, 0x73, 0x73, 0x69, 0x6e, 0x67, 0x10, + 0xa3, 0x03, 0x12, 0x0c, 0x0a, 0x07, 0x46, 0x69, 0x6e, 0x6e, 0x68, 0x75, 0x62, 0x10, 0xa4, 0x03, + 0x12, 0x0b, 0x0a, 0x06, 0x54, 0x69, 0x69, 0x6e, 0x67, 0x6f, 0x10, 0xa5, 0x03, 0x12, 0x10, 0x0a, + 0x0b, 0x52, 0x69, 0x6e, 0x67, 0x43, 0x65, 0x6e, 0x74, 0x72, 0x61, 0x6c, 0x10, 0xa6, 0x03, 0x12, + 0x0b, 0x0a, 0x06, 0x46, 0x69, 0x6e, 0x61, 0x67, 0x65, 0x10, 0xa7, 0x03, 0x12, 0x0b, 0x0a, 0x06, + 0x45, 0x64, 0x61, 0x6d, 0x61, 0x6d, 0x10, 0xa8, 0x03, 0x12, 0x10, 0x0a, 0x0b, 0x48, 0x79, 0x70, + 0x65, 0x41, 0x75, 0x64, 0x69, 0x74, 0x6f, 0x72, 0x10, 0xa9, 0x03, 0x12, 0x0a, 0x0a, 0x05, 0x47, + 0x65, 0x6e, 0x67, 0x6f, 0x10, 0xaa, 0x03, 0x12, 0x0a, 0x0a, 0x05, 0x46, 0x72, 0x6f, 0x6e, 0x74, + 0x10, 0xab, 0x03, 0x12, 0x0e, 0x0a, 0x09, 0x46, 0x6c, 0x65, 0x65, 0x74, 0x62, 0x61, 0x73, 0x65, + 0x10, 0xac, 0x03, 0x12, 0x0b, 0x0a, 0x06, 0x42, 0x75, 0x62, 0x62, 0x6c, 0x65, 0x10, 0xad, 0x03, + 0x12, 0x0f, 0x0a, 0x0a, 0x42, 0x61, 0x6e, 0x6e, 0x65, 0x72, 0x62, 0x65, 0x61, 0x72, 0x10, 0xae, + 0x03, 0x12, 0x0b, 0x0a, 0x06, 0x41, 0x64, 0x7a, 0x75, 0x6e, 0x61, 0x10, 0xaf, 0x03, 0x12, 0x13, + 0x0a, 0x0e, 0x42, 0x69, 0x74, 0x63, 0x6f, 0x69, 0x6e, 0x41, 0x76, 0x65, 0x72, 0x61, 0x67, 0x65, + 0x10, 0xb0, 0x03, 0x12, 0x0f, 0x0a, 0x0a, 0x43, 0x6f, 0x6d, 0x6d, 0x65, 0x72, 0x63, 0x65, 0x4a, + 0x53, 0x10, 0xb1, 0x03, 0x12, 0x13, 0x0a, 0x0e, 0x44, 0x65, 0x74, 0x65, 0x63, 0x74, 0x4c, 0x61, + 0x6e, 0x67, 0x75, 0x61, 0x67, 0x65, 0x10, 0xb2, 0x03, 0x12, 0x0d, 0x0a, 0x08, 0x46, 0x61, 0x6b, + 0x65, 0x4a, 0x53, 0x4f, 0x4e, 0x10, 0xb3, 0x03, 0x12, 0x10, 0x0a, 0x0b, 0x47, 0x72, 0x61, 0x70, + 0x68, 0x68, 0x6f, 0x70, 0x70, 0x65, 0x72, 0x10, 0xb4, 0x03, 0x12, 0x0d, 0x0a, 0x08, 0x4c, 0x65, + 0x78, 0x69, 0x67, 0x72, 0x61, 0x6d, 0x10, 0xb5, 0x03, 0x12, 0x10, 0x0a, 0x0b, 0x4c, 0x69, 0x6e, + 0x6b, 0x50, 0x72, 0x65, 0x76, 0x69, 0x65, 0x77, 0x10, 0xb6, 0x03, 0x12, 0x0e, 0x0a, 0x09, 0x4e, + 0x75, 0x6d, 0x76, 0x65, 0x72, 0x69, 0x66, 0x79, 0x10, 0xb7, 0x03, 0x12, 0x0f, 0x0a, 0x0a, 0x50, + 0x72, 0x6f, 0x78, 0x79, 0x43, 0x72, 0x61, 0x77, 0x6c, 0x10, 0xb8, 0x03, 0x12, 0x0f, 0x0a, 0x0a, + 0x5a, 0x69, 0x70, 0x43, 0x6f, 0x64, 0x65, 0x41, 0x50, 0x49, 0x10, 0xb9, 0x03, 0x12, 0x0e, 0x0a, + 0x09, 0x43, 0x6f, 0x6d, 0x65, 0x74, 0x63, 0x68, 0x61, 0x74, 0x10, 0xba, 0x03, 0x12, 0x0b, 0x0a, + 0x06, 0x4b, 0x65, 0x79, 0x67, 0x65, 0x6e, 0x10, 0xbb, 0x03, 0x12, 0x0d, 0x0a, 0x08, 0x4d, 0x69, + 0x78, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x10, 0xbc, 0x03, 0x12, 0x0c, 0x0a, 0x07, 0x54, 0x61, 0x74, + 0x75, 0x6d, 0x49, 0x4f, 0x10, 0xbd, 0x03, 0x12, 0x0c, 0x0a, 0x07, 0x54, 0x6d, 0x65, 0x74, 0x72, + 0x69, 0x63, 0x10, 0xbe, 0x03, 0x12, 0x0b, 0x0a, 0x06, 0x4c, 0x61, 0x73, 0x74, 0x66, 0x6d, 0x10, + 0xbf, 0x03, 0x12, 0x0d, 0x0a, 0x08, 0x42, 0x72, 0x6f, 0x77, 0x73, 0x68, 0x6f, 0x74, 0x10, 0xc0, + 0x03, 0x12, 0x0c, 0x0a, 0x07, 0x4a, 0x53, 0x4f, 0x4e, 0x62, 0x69, 0x6e, 0x10, 0xc1, 0x03, 0x12, + 0x0f, 0x0a, 0x0a, 0x4c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x51, 0x10, 0xc2, 0x03, + 0x12, 0x12, 0x0a, 0x0d, 0x53, 0x63, 0x72, 0x65, 0x65, 0x6e, 0x73, 0x68, 0x6f, 0x74, 0x41, 0x50, + 0x49, 0x10, 0xc3, 0x03, 0x12, 0x11, 0x0a, 0x0c, 0x57, 0x65, 0x61, 0x74, 0x68, 0x65, 0x72, 0x53, + 0x74, 0x61, 0x63, 0x6b, 0x10, 0xc4, 0x03, 0x12, 0x0c, 0x0a, 0x07, 0x41, 0x6d, 0x61, 0x64, 0x65, + 0x75, 0x73, 0x10, 0xc5, 0x03, 0x12, 0x0f, 0x0a, 0x0a, 0x46, 0x6f, 0x75, 0x72, 0x53, 0x71, 0x75, + 0x61, 0x72, 0x65, 0x10, 0xc6, 0x03, 0x12, 0x0b, 0x0a, 0x06, 0x46, 0x6c, 0x69, 0x63, 0x6b, 0x72, + 0x10, 0xc7, 0x03, 0x12, 0x0e, 0x0a, 0x09, 0x43, 0x6c, 0x69, 0x63, 0x6b, 0x48, 0x65, 0x6c, 0x70, + 0x10, 0xc8, 0x03, 0x12, 0x0a, 0x0a, 0x05, 0x41, 0x6d, 0x62, 0x65, 0x65, 0x10, 0xc9, 0x03, 0x12, + 0x0d, 0x0a, 0x08, 0x41, 0x70, 0x69, 0x32, 0x43, 0x61, 0x72, 0x74, 0x10, 0xca, 0x03, 0x12, 0x0f, + 0x0a, 0x0a, 0x48, 0x79, 0x70, 0x65, 0x72, 0x74, 0x72, 0x61, 0x63, 0x6b, 0x10, 0xcb, 0x03, 0x12, + 0x0e, 0x0a, 0x09, 0x4b, 0x61, 0x6b, 0x61, 0x6f, 0x54, 0x61, 0x6c, 0x6b, 0x10, 0xcc, 0x03, 0x12, + 0x0c, 0x0a, 0x07, 0x52, 0x69, 0x74, 0x65, 0x4b, 0x69, 0x74, 0x10, 0xcd, 0x03, 0x12, 0x11, 0x0a, + 0x0c, 0x53, 0x68, 0x75, 0x74, 0x74, 0x65, 0x72, 0x73, 0x74, 0x6f, 0x63, 0x6b, 0x10, 0xce, 0x03, + 0x12, 0x0e, 0x0a, 0x09, 0x54, 0x65, 0x78, 0x74, 0x32, 0x44, 0x61, 0x74, 0x61, 0x10, 0xcf, 0x03, + 0x12, 0x13, 0x0a, 0x0e, 0x59, 0x6f, 0x75, 0x4e, 0x65, 0x65, 0x64, 0x41, 0x42, 0x75, 0x64, 0x67, + 0x65, 0x74, 0x10, 0xd0, 0x03, 0x12, 0x0c, 0x0a, 0x07, 0x43, 0x72, 0x69, 0x63, 0x6b, 0x65, 0x74, + 0x10, 0xd1, 0x03, 0x12, 0x0e, 0x0a, 0x09, 0x46, 0x69, 0x6c, 0x65, 0x73, 0x74, 0x61, 0x63, 0x6b, + 0x10, 0xd2, 0x03, 0x12, 0x0a, 0x0a, 0x05, 0x47, 0x79, 0x61, 0x7a, 0x6f, 0x10, 0xd3, 0x03, 0x12, + 0x0e, 0x0a, 0x09, 0x4d, 0x61, 0x76, 0x65, 0x6e, 0x6c, 0x69, 0x6e, 0x6b, 0x10, 0xd4, 0x03, 0x12, + 0x0b, 0x0a, 0x06, 0x53, 0x68, 0x65, 0x65, 0x74, 0x79, 0x10, 0xd5, 0x03, 0x12, 0x0f, 0x0a, 0x0a, + 0x53, 0x70, 0x6f, 0x72, 0x74, 0x73, 0x6d, 0x6f, 0x6e, 0x6b, 0x10, 0xd6, 0x03, 0x12, 0x0e, 0x0a, + 0x09, 0x53, 0x74, 0x6f, 0x63, 0x6b, 0x64, 0x61, 0x74, 0x61, 0x10, 0xd7, 0x03, 0x12, 0x0d, 0x0a, + 0x08, 0x55, 0x6e, 0x73, 0x70, 0x6c, 0x61, 0x73, 0x68, 0x10, 0xd8, 0x03, 0x12, 0x0e, 0x0a, 0x09, + 0x41, 0x6c, 0x6c, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x73, 0x10, 0xd9, 0x03, 0x12, 0x11, 0x0a, 0x0c, + 0x43, 0x61, 0x6c, 0x6f, 0x72, 0x69, 0x65, 0x4e, 0x69, 0x6e, 0x6a, 0x61, 0x10, 0xda, 0x03, 0x12, + 0x0e, 0x0a, 0x09, 0x57, 0x61, 0x6c, 0x6b, 0x53, 0x63, 0x6f, 0x72, 0x65, 0x10, 0xdb, 0x03, 0x12, + 0x0b, 0x0a, 0x06, 0x53, 0x74, 0x72, 0x61, 0x76, 0x61, 0x10, 0xdc, 0x03, 0x12, 0x0b, 0x0a, 0x06, + 0x43, 0x69, 0x63, 0x65, 0x72, 0x6f, 0x10, 0xdd, 0x03, 0x12, 0x0e, 0x0a, 0x09, 0x49, 0x50, 0x51, + 0x75, 0x61, 0x6c, 0x69, 0x74, 0x79, 0x10, 0xde, 0x03, 0x12, 0x11, 0x0a, 0x0c, 0x50, 0x61, 0x72, + 0x61, 0x6c, 0x6c, 0x65, 0x6c, 0x44, 0x6f, 0x74, 0x73, 0x10, 0xdf, 0x03, 0x12, 0x0c, 0x0a, 0x07, + 0x52, 0x6f, 0x61, 0x72, 0x69, 0x6e, 0x67, 0x10, 0xe0, 0x03, 0x12, 0x0c, 0x0a, 0x07, 0x4d, 0x61, + 0x69, 0x6c, 0x73, 0x61, 0x63, 0x10, 0xe1, 0x03, 0x12, 0x0a, 0x0a, 0x05, 0x57, 0x68, 0x6f, 0x78, + 0x79, 0x10, 0xe2, 0x03, 0x12, 0x11, 0x0a, 0x0c, 0x57, 0x6f, 0x72, 0x6c, 0x64, 0x57, 0x65, 0x61, + 0x74, 0x68, 0x65, 0x72, 0x10, 0xe3, 0x03, 0x12, 0x0e, 0x0a, 0x09, 0x41, 0x70, 0x69, 0x46, 0x6f, + 0x6e, 0x69, 0x63, 0x61, 0x10, 0xe4, 0x03, 0x12, 0x0b, 0x0a, 0x06, 0x41, 0x79, 0x6c, 0x69, 0x65, + 0x6e, 0x10, 0xe5, 0x03, 0x12, 0x0c, 0x0a, 0x07, 0x47, 0x65, 0x6f, 0x63, 0x6f, 0x64, 0x65, 0x10, + 0xe6, 0x03, 0x12, 0x0f, 0x0a, 0x0a, 0x49, 0x63, 0x6f, 0x6e, 0x46, 0x69, 0x6e, 0x64, 0x65, 0x72, + 0x10, 0xe7, 0x03, 0x12, 0x0a, 0x0a, 0x05, 0x49, 0x70, 0x69, 0x66, 0x79, 0x10, 0xe8, 0x03, 0x12, + 0x12, 0x0a, 0x0d, 0x4c, 0x61, 0x6e, 0x67, 0x75, 0x61, 0x67, 0x65, 0x4c, 0x61, 0x79, 0x65, 0x72, + 0x10, 0xe9, 0x03, 0x12, 0x08, 0x0a, 0x03, 0x4c, 0x6f, 0x62, 0x10, 0xea, 0x03, 0x12, 0x0e, 0x0a, + 0x09, 0x4f, 0x6e, 0x57, 0x61, 0x74, 0x65, 0x72, 0x49, 0x4f, 0x10, 0xeb, 0x03, 0x12, 0x0d, 0x0a, + 0x08, 0x50, 0x61, 0x73, 0x74, 0x65, 0x62, 0x69, 0x6e, 0x10, 0xec, 0x03, 0x12, 0x0d, 0x0a, 0x08, + 0x50, 0x64, 0x66, 0x4c, 0x61, 0x79, 0x65, 0x72, 0x10, 0xed, 0x03, 0x12, 0x0c, 0x0a, 0x07, 0x50, + 0x69, 0x78, 0x61, 0x62, 0x61, 0x79, 0x10, 0xee, 0x03, 0x12, 0x0b, 0x0a, 0x06, 0x52, 0x65, 0x61, + 0x64, 0x4d, 0x65, 0x10, 0xef, 0x03, 0x12, 0x0d, 0x0a, 0x08, 0x56, 0x61, 0x74, 0x4c, 0x61, 0x79, + 0x65, 0x72, 0x10, 0xf0, 0x03, 0x12, 0x0f, 0x0a, 0x0a, 0x56, 0x69, 0x72, 0x75, 0x73, 0x54, 0x6f, + 0x74, 0x61, 0x6c, 0x10, 0xf1, 0x03, 0x12, 0x0e, 0x0a, 0x09, 0x41, 0x69, 0x72, 0x56, 0x69, 0x73, + 0x75, 0x61, 0x6c, 0x10, 0xf2, 0x03, 0x12, 0x13, 0x0a, 0x0e, 0x43, 0x75, 0x72, 0x72, 0x65, 0x6e, + 0x63, 0x79, 0x66, 0x72, 0x65, 0x61, 0x6b, 0x73, 0x10, 0xf3, 0x03, 0x12, 0x0b, 0x0a, 0x06, 0x44, + 0x75, 0x66, 0x66, 0x65, 0x6c, 0x10, 0xf4, 0x03, 0x12, 0x0b, 0x0a, 0x06, 0x46, 0x6c, 0x61, 0x74, + 0x49, 0x4f, 0x10, 0xf5, 0x03, 0x12, 0x08, 0x0a, 0x03, 0x4d, 0x33, 0x6f, 0x10, 0xf6, 0x03, 0x12, + 0x0b, 0x0a, 0x06, 0x4d, 0x65, 0x73, 0x69, 0x62, 0x6f, 0x10, 0xf7, 0x03, 0x12, 0x0b, 0x0a, 0x06, + 0x4f, 0x70, 0x65, 0x6e, 0x75, 0x76, 0x10, 0xf8, 0x03, 0x12, 0x0d, 0x0a, 0x08, 0x53, 0x6e, 0x69, + 0x70, 0x63, 0x61, 0x72, 0x74, 0x10, 0xf9, 0x03, 0x12, 0x0d, 0x0a, 0x08, 0x42, 0x65, 0x73, 0x74, + 0x74, 0x69, 0x6d, 0x65, 0x10, 0xfa, 0x03, 0x12, 0x10, 0x0a, 0x0b, 0x48, 0x61, 0x70, 0x70, 0x79, + 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, 0x10, 0xfb, 0x03, 0x12, 0x0d, 0x0a, 0x08, 0x48, 0x75, 0x6d, + 0x61, 0x6e, 0x69, 0x74, 0x79, 0x10, 0xfc, 0x03, 0x12, 0x0b, 0x0a, 0x06, 0x49, 0x6d, 0x70, 0x61, + 0x6c, 0x61, 0x10, 0xfd, 0x03, 0x12, 0x10, 0x0a, 0x0b, 0x4c, 0x6f, 0x67, 0x69, 0x6e, 0x72, 0x61, + 0x64, 0x69, 0x75, 0x73, 0x10, 0xfe, 0x03, 0x12, 0x0e, 0x0a, 0x09, 0x41, 0x75, 0x74, 0x6f, 0x50, + 0x69, 0x6c, 0x6f, 0x74, 0x10, 0xff, 0x03, 0x12, 0x0b, 0x0a, 0x06, 0x42, 0x69, 0x74, 0x6d, 0x65, + 0x78, 0x10, 0x80, 0x04, 0x12, 0x0d, 0x0a, 0x08, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x44, 0x6f, 0x63, + 0x10, 0x81, 0x04, 0x12, 0x0c, 0x0a, 0x07, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x72, 0x69, 0x10, 0x82, + 0x04, 0x12, 0x0d, 0x0a, 0x08, 0x50, 0x64, 0x66, 0x53, 0x68, 0x69, 0x66, 0x74, 0x10, 0x83, 0x04, + 0x12, 0x0d, 0x0a, 0x08, 0x50, 0x6f, 0x6c, 0x6f, 0x6e, 0x69, 0x65, 0x78, 0x10, 0x84, 0x04, 0x12, + 0x19, 0x0a, 0x14, 0x52, 0x65, 0x73, 0x74, 0x70, 0x61, 0x63, 0x6b, 0x48, 0x74, 0x6d, 0x6c, 0x54, + 0x6f, 0x50, 0x64, 0x66, 0x41, 0x50, 0x49, 0x10, 0x85, 0x04, 0x12, 0x1a, 0x0a, 0x15, 0x52, 0x65, + 0x73, 0x74, 0x70, 0x61, 0x63, 0x6b, 0x53, 0x63, 0x72, 0x65, 0x65, 0x6e, 0x73, 0x68, 0x6f, 0x74, + 0x41, 0x50, 0x49, 0x10, 0x86, 0x04, 0x12, 0x16, 0x0a, 0x11, 0x53, 0x68, 0x75, 0x74, 0x74, 0x65, + 0x72, 0x73, 0x74, 0x6f, 0x63, 0x6b, 0x4f, 0x41, 0x75, 0x74, 0x68, 0x10, 0x87, 0x04, 0x12, 0x10, + 0x0a, 0x0b, 0x53, 0x6b, 0x79, 0x42, 0x69, 0x6f, 0x6d, 0x65, 0x74, 0x72, 0x79, 0x10, 0x88, 0x04, + 0x12, 0x0e, 0x0a, 0x09, 0x41, 0x62, 0x75, 0x73, 0x65, 0x49, 0x50, 0x44, 0x42, 0x10, 0x89, 0x04, + 0x12, 0x10, 0x0a, 0x0b, 0x41, 0x6c, 0x65, 0x74, 0x68, 0x65, 0x69, 0x61, 0x41, 0x70, 0x69, 0x10, + 0x8a, 0x04, 0x12, 0x0c, 0x0a, 0x07, 0x42, 0x6c, 0x69, 0x74, 0x41, 0x70, 0x70, 0x10, 0x8b, 0x04, + 0x12, 0x0b, 0x0a, 0x06, 0x43, 0x65, 0x6e, 0x73, 0x79, 0x73, 0x10, 0x8c, 0x04, 0x12, 0x0d, 0x0a, + 0x08, 0x43, 0x6c, 0x6f, 0x76, 0x65, 0x72, 0x6c, 0x79, 0x10, 0x8d, 0x04, 0x12, 0x11, 0x0a, 0x0c, + 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x72, 0x79, 0x4c, 0x61, 0x79, 0x65, 0x72, 0x10, 0x8e, 0x04, 0x12, + 0x0b, 0x0a, 0x06, 0x46, 0x69, 0x6c, 0x65, 0x49, 0x4f, 0x10, 0x8f, 0x04, 0x12, 0x0e, 0x0a, 0x09, + 0x46, 0x6c, 0x69, 0x67, 0x68, 0x74, 0x41, 0x70, 0x69, 0x10, 0x90, 0x04, 0x12, 0x0d, 0x0a, 0x08, + 0x47, 0x65, 0x6f, 0x61, 0x70, 0x69, 0x66, 0x79, 0x10, 0x91, 0x04, 0x12, 0x0d, 0x0a, 0x08, 0x49, + 0x50, 0x69, 0x6e, 0x66, 0x6f, 0x44, 0x42, 0x10, 0x92, 0x04, 0x12, 0x0f, 0x0a, 0x0a, 0x4d, 0x65, + 0x64, 0x69, 0x61, 0x53, 0x74, 0x61, 0x63, 0x6b, 0x10, 0x93, 0x04, 0x12, 0x13, 0x0a, 0x0e, 0x4e, + 0x61, 0x73, 0x64, 0x61, 0x71, 0x44, 0x61, 0x74, 0x61, 0x4c, 0x69, 0x6e, 0x6b, 0x10, 0x94, 0x04, + 0x12, 0x11, 0x0a, 0x0c, 0x4f, 0x70, 0x65, 0x6e, 0x43, 0x61, 0x67, 0x65, 0x44, 0x61, 0x74, 0x61, + 0x10, 0x95, 0x04, 0x12, 0x0d, 0x0a, 0x08, 0x50, 0x61, 0x79, 0x6d, 0x6f, 0x6e, 0x67, 0x6f, 0x10, + 0x96, 0x04, 0x12, 0x12, 0x0a, 0x0d, 0x50, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x74, + 0x61, 0x63, 0x6b, 0x10, 0x97, 0x04, 0x12, 0x0e, 0x0a, 0x09, 0x52, 0x65, 0x62, 0x72, 0x61, 0x6e, + 0x64, 0x6c, 0x79, 0x10, 0x98, 0x04, 0x12, 0x14, 0x0a, 0x0f, 0x53, 0x63, 0x72, 0x65, 0x65, 0x6e, + 0x73, 0x68, 0x6f, 0x74, 0x4c, 0x61, 0x79, 0x65, 0x72, 0x10, 0x99, 0x04, 0x12, 0x0b, 0x0a, 0x06, + 0x53, 0x74, 0x79, 0x74, 0x63, 0x68, 0x10, 0x9a, 0x04, 0x12, 0x0c, 0x0a, 0x07, 0x55, 0x6e, 0x70, + 0x6c, 0x75, 0x67, 0x67, 0x10, 0x9b, 0x04, 0x12, 0x10, 0x0a, 0x0b, 0x55, 0x50, 0x43, 0x44, 0x61, + 0x74, 0x61, 0x62, 0x61, 0x73, 0x65, 0x10, 0x9c, 0x04, 0x12, 0x0e, 0x0a, 0x09, 0x55, 0x73, 0x65, + 0x72, 0x53, 0x74, 0x61, 0x63, 0x6b, 0x10, 0x9d, 0x04, 0x12, 0x0e, 0x0a, 0x09, 0x47, 0x65, 0x6f, + 0x63, 0x6f, 0x64, 0x69, 0x66, 0x79, 0x10, 0x9e, 0x04, 0x12, 0x10, 0x0a, 0x0b, 0x4e, 0x65, 0x77, + 0x73, 0x63, 0x61, 0x74, 0x63, 0x68, 0x65, 0x72, 0x10, 0x9f, 0x04, 0x12, 0x0e, 0x0a, 0x09, 0x4e, + 0x69, 0x63, 0x65, 0x72, 0x65, 0x70, 0x6c, 0x79, 0x10, 0xa0, 0x04, 0x12, 0x11, 0x0a, 0x0c, 0x50, + 0x61, 0x72, 0x74, 0x6e, 0x65, 0x72, 0x73, 0x74, 0x61, 0x63, 0x6b, 0x10, 0xa1, 0x04, 0x12, 0x0d, + 0x0a, 0x08, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x34, 0x6d, 0x65, 0x10, 0xa2, 0x04, 0x12, 0x0e, 0x0a, + 0x09, 0x53, 0x63, 0x72, 0x61, 0x70, 0x65, 0x6f, 0x77, 0x6c, 0x10, 0xa3, 0x04, 0x12, 0x10, 0x0a, + 0x0b, 0x53, 0x63, 0x72, 0x61, 0x70, 0x69, 0x6e, 0x67, 0x44, 0x6f, 0x67, 0x10, 0xa4, 0x04, 0x12, + 0x0b, 0x0a, 0x06, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6b, 0x10, 0xa5, 0x04, 0x12, 0x0e, 0x0a, 0x09, + 0x56, 0x65, 0x72, 0x69, 0x70, 0x68, 0x6f, 0x6e, 0x65, 0x10, 0xa6, 0x04, 0x12, 0x10, 0x0a, 0x0b, + 0x57, 0x65, 0x62, 0x73, 0x63, 0x72, 0x61, 0x70, 0x69, 0x6e, 0x67, 0x10, 0xa7, 0x04, 0x12, 0x0e, + 0x0a, 0x09, 0x5a, 0x65, 0x6e, 0x73, 0x63, 0x72, 0x61, 0x70, 0x65, 0x10, 0xa8, 0x04, 0x12, 0x0c, + 0x0a, 0x07, 0x5a, 0x65, 0x6e, 0x73, 0x65, 0x72, 0x70, 0x10, 0xa9, 0x04, 0x12, 0x0c, 0x0a, 0x07, + 0x43, 0x6f, 0x69, 0x6e, 0x41, 0x70, 0x69, 0x10, 0xaa, 0x04, 0x12, 0x0b, 0x0a, 0x06, 0x47, 0x69, + 0x74, 0x74, 0x65, 0x72, 0x10, 0xab, 0x04, 0x12, 0x09, 0x0a, 0x04, 0x48, 0x6f, 0x73, 0x74, 0x10, + 0xac, 0x04, 0x12, 0x0d, 0x0a, 0x08, 0x49, 0x65, 0x78, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x10, 0xad, + 0x04, 0x12, 0x0d, 0x0a, 0x08, 0x52, 0x65, 0x73, 0x74, 0x70, 0x61, 0x63, 0x6b, 0x10, 0xae, 0x04, + 0x12, 0x0f, 0x0a, 0x0a, 0x53, 0x63, 0x72, 0x61, 0x70, 0x65, 0x72, 0x42, 0x6f, 0x78, 0x10, 0xaf, + 0x04, 0x12, 0x10, 0x0a, 0x0b, 0x53, 0x63, 0x72, 0x61, 0x70, 0x69, 0x6e, 0x67, 0x41, 0x6e, 0x74, + 0x10, 0xb0, 0x04, 0x12, 0x0e, 0x0a, 0x09, 0x53, 0x65, 0x72, 0x70, 0x53, 0x74, 0x61, 0x63, 0x6b, + 0x10, 0xb1, 0x04, 0x12, 0x12, 0x0a, 0x0d, 0x53, 0x6d, 0x61, 0x72, 0x74, 0x79, 0x53, 0x74, 0x72, + 0x65, 0x65, 0x74, 0x73, 0x10, 0xb2, 0x04, 0x12, 0x11, 0x0a, 0x0c, 0x54, 0x69, 0x63, 0x6b, 0x65, + 0x74, 0x4d, 0x61, 0x73, 0x74, 0x65, 0x72, 0x10, 0xb3, 0x04, 0x12, 0x12, 0x0a, 0x0d, 0x41, 0x76, + 0x69, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x63, 0x6b, 0x10, 0xb4, 0x04, 0x12, 0x0d, + 0x0a, 0x08, 0x42, 0x6f, 0x6d, 0x62, 0x42, 0x6f, 0x6d, 0x62, 0x10, 0xb5, 0x04, 0x12, 0x10, 0x0a, + 0x0b, 0x43, 0x6f, 0x6d, 0x6d, 0x6f, 0x64, 0x69, 0x74, 0x69, 0x65, 0x73, 0x10, 0xb6, 0x04, 0x12, + 0x0a, 0x0a, 0x05, 0x44, 0x66, 0x75, 0x73, 0x65, 0x10, 0xb7, 0x04, 0x12, 0x0b, 0x0a, 0x06, 0x45, + 0x64, 0x65, 0x6e, 0x41, 0x49, 0x10, 0xb8, 0x04, 0x12, 0x0e, 0x0a, 0x09, 0x47, 0x6c, 0x61, 0x73, + 0x73, 0x6e, 0x6f, 0x64, 0x65, 0x10, 0xb9, 0x04, 0x12, 0x09, 0x0a, 0x04, 0x47, 0x75, 0x72, 0x75, + 0x10, 0xba, 0x04, 0x12, 0x09, 0x0a, 0x04, 0x48, 0x69, 0x76, 0x65, 0x10, 0xbb, 0x04, 0x12, 0x0c, + 0x0a, 0x07, 0x48, 0x69, 0x76, 0x65, 0x61, 0x67, 0x65, 0x10, 0xbc, 0x04, 0x12, 0x0c, 0x0a, 0x07, + 0x4b, 0x69, 0x63, 0x6b, 0x62, 0x6f, 0x78, 0x10, 0xbd, 0x04, 0x12, 0x0d, 0x0a, 0x08, 0x50, 0x61, + 0x73, 0x73, 0x62, 0x61, 0x73, 0x65, 0x10, 0xbe, 0x04, 0x12, 0x0f, 0x0a, 0x0a, 0x50, 0x6f, 0x73, + 0x74, 0x61, 0x67, 0x65, 0x41, 0x70, 0x70, 0x10, 0xbf, 0x04, 0x12, 0x0e, 0x0a, 0x09, 0x50, 0x75, + 0x72, 0x65, 0x53, 0x74, 0x61, 0x6b, 0x65, 0x10, 0xc0, 0x04, 0x12, 0x0b, 0x0a, 0x06, 0x51, 0x75, + 0x62, 0x6f, 0x6c, 0x65, 0x10, 0xc1, 0x04, 0x12, 0x14, 0x0a, 0x0f, 0x43, 0x61, 0x72, 0x62, 0x6f, + 0x6e, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, 0x10, 0xc2, 0x04, 0x12, 0x0d, 0x0a, + 0x08, 0x49, 0x6e, 0x74, 0x72, 0x69, 0x6e, 0x69, 0x6f, 0x10, 0xc3, 0x04, 0x12, 0x15, 0x0a, 0x0c, + 0x51, 0x75, 0x69, 0x63, 0x6b, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x10, 0xc4, 0x04, 0x1a, + 0x02, 0x08, 0x01, 0x12, 0x10, 0x0a, 0x0b, 0x53, 0x63, 0x72, 0x61, 0x70, 0x65, 0x53, 0x74, 0x61, + 0x63, 0x6b, 0x10, 0xc5, 0x04, 0x12, 0x19, 0x0a, 0x14, 0x54, 0x65, 0x63, 0x68, 0x6e, 0x69, 0x63, + 0x61, 0x6c, 0x41, 0x6e, 0x61, 0x6c, 0x79, 0x73, 0x69, 0x73, 0x41, 0x70, 0x69, 0x10, 0xc6, 0x04, + 0x12, 0x0c, 0x0a, 0x07, 0x55, 0x72, 0x6c, 0x73, 0x63, 0x61, 0x6e, 0x10, 0xc7, 0x04, 0x12, 0x0e, + 0x0a, 0x09, 0x42, 0x61, 0x73, 0x65, 0x41, 0x70, 0x69, 0x49, 0x4f, 0x10, 0xc8, 0x04, 0x12, 0x0c, + 0x0a, 0x07, 0x44, 0x61, 0x69, 0x6c, 0x79, 0x43, 0x4f, 0x10, 0xc9, 0x04, 0x12, 0x08, 0x0a, 0x03, + 0x54, 0x4c, 0x79, 0x10, 0xca, 0x04, 0x12, 0x0d, 0x0a, 0x08, 0x53, 0x68, 0x6f, 0x72, 0x74, 0x63, + 0x75, 0x74, 0x10, 0xcb, 0x04, 0x12, 0x0e, 0x0a, 0x09, 0x41, 0x70, 0x70, 0x66, 0x6f, 0x6c, 0x6c, + 0x6f, 0x77, 0x10, 0xcc, 0x04, 0x12, 0x0e, 0x0a, 0x09, 0x54, 0x68, 0x69, 0x6e, 0x6b, 0x69, 0x66, + 0x69, 0x63, 0x10, 0xcd, 0x04, 0x12, 0x0b, 0x0a, 0x06, 0x46, 0x65, 0x65, 0x64, 0x6c, 0x79, 0x10, + 0xce, 0x04, 0x12, 0x0f, 0x0a, 0x0a, 0x53, 0x74, 0x69, 0x74, 0x63, 0x68, 0x64, 0x61, 0x74, 0x61, + 0x10, 0xcf, 0x04, 0x12, 0x0d, 0x0a, 0x08, 0x46, 0x65, 0x74, 0x63, 0x68, 0x72, 0x73, 0x73, 0x10, + 0xd0, 0x04, 0x12, 0x11, 0x0a, 0x0c, 0x53, 0x69, 0x67, 0x6e, 0x75, 0x70, 0x67, 0x65, 0x6e, 0x69, + 0x75, 0x73, 0x10, 0xd1, 0x04, 0x12, 0x0f, 0x0a, 0x0a, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, + 0x72, 0x69, 0x74, 0x10, 0xd2, 0x04, 0x12, 0x0f, 0x0a, 0x0a, 0x4f, 0x70, 0x74, 0x69, 0x6d, 0x69, + 0x7a, 0x65, 0x6c, 0x79, 0x10, 0xd3, 0x04, 0x12, 0x0d, 0x0a, 0x08, 0x4f, 0x63, 0x72, 0x53, 0x70, + 0x61, 0x63, 0x65, 0x10, 0xd4, 0x04, 0x12, 0x0f, 0x0a, 0x0a, 0x57, 0x65, 0x61, 0x74, 0x68, 0x65, + 0x72, 0x42, 0x69, 0x74, 0x10, 0xd5, 0x04, 0x12, 0x0c, 0x0a, 0x07, 0x42, 0x75, 0x64, 0x64, 0x79, + 0x4e, 0x53, 0x10, 0xd6, 0x04, 0x12, 0x0b, 0x0a, 0x06, 0x5a, 0x69, 0x70, 0x41, 0x50, 0x49, 0x10, + 0xd7, 0x04, 0x12, 0x0d, 0x0a, 0x08, 0x5a, 0x69, 0x70, 0x42, 0x6f, 0x6f, 0x6b, 0x73, 0x10, 0xd8, + 0x04, 0x12, 0x0c, 0x0a, 0x07, 0x4f, 0x6e, 0x65, 0x64, 0x65, 0x73, 0x6b, 0x10, 0xd9, 0x04, 0x12, + 0x0c, 0x0a, 0x07, 0x42, 0x75, 0x67, 0x68, 0x65, 0x72, 0x64, 0x10, 0xda, 0x04, 0x12, 0x0f, 0x0a, + 0x0a, 0x42, 0x6c, 0x61, 0x7a, 0x65, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x10, 0xdb, 0x04, 0x12, 0x0d, + 0x0a, 0x08, 0x41, 0x75, 0x74, 0x6f, 0x64, 0x65, 0x73, 0x6b, 0x10, 0xdc, 0x04, 0x12, 0x08, 0x0a, + 0x03, 0x54, 0x72, 0x75, 0x10, 0xdd, 0x04, 0x12, 0x0c, 0x0a, 0x07, 0x55, 0x6e, 0x69, 0x66, 0x79, + 0x49, 0x44, 0x10, 0xde, 0x04, 0x12, 0x0c, 0x0a, 0x07, 0x54, 0x72, 0x69, 0x6d, 0x62, 0x6c, 0x65, + 0x10, 0xdf, 0x04, 0x12, 0x0b, 0x0a, 0x06, 0x53, 0x6d, 0x6f, 0x6f, 0x63, 0x68, 0x10, 0xe0, 0x04, + 0x12, 0x0e, 0x0a, 0x09, 0x53, 0x65, 0x6d, 0x61, 0x70, 0x68, 0x6f, 0x72, 0x65, 0x10, 0xe1, 0x04, + 0x12, 0x0b, 0x0a, 0x06, 0x54, 0x65, 0x6c, 0x6e, 0x79, 0x78, 0x10, 0xe2, 0x04, 0x12, 0x0f, 0x0a, + 0x0a, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x6c, 0x77, 0x69, 0x72, 0x65, 0x10, 0xe3, 0x04, 0x12, 0x0e, + 0x0a, 0x09, 0x54, 0x65, 0x78, 0x74, 0x6d, 0x61, 0x67, 0x69, 0x63, 0x10, 0xe4, 0x04, 0x12, 0x0e, + 0x0a, 0x09, 0x53, 0x65, 0x72, 0x70, 0x68, 0x6f, 0x75, 0x73, 0x65, 0x10, 0xe5, 0x04, 0x12, 0x0b, + 0x0a, 0x06, 0x50, 0x6c, 0x61, 0x6e, 0x79, 0x6f, 0x10, 0xe6, 0x04, 0x12, 0x0f, 0x0a, 0x0a, 0x53, + 0x69, 0x6d, 0x70, 0x6c, 0x79, 0x62, 0x6f, 0x6f, 0x6b, 0x10, 0xe7, 0x04, 0x12, 0x09, 0x0a, 0x04, + 0x56, 0x79, 0x74, 0x65, 0x10, 0xe8, 0x04, 0x12, 0x0a, 0x0a, 0x05, 0x4e, 0x79, 0x6c, 0x61, 0x73, + 0x10, 0xe9, 0x04, 0x12, 0x0d, 0x0a, 0x08, 0x53, 0x71, 0x75, 0x61, 0x72, 0x65, 0x75, 0x70, 0x10, + 0xea, 0x04, 0x12, 0x0e, 0x0a, 0x09, 0x44, 0x61, 0x6e, 0x64, 0x65, 0x6c, 0x69, 0x6f, 0x6e, 0x10, + 0xeb, 0x04, 0x12, 0x11, 0x0a, 0x08, 0x44, 0x61, 0x74, 0x61, 0x46, 0x69, 0x72, 0x65, 0x10, 0xec, + 0x04, 0x1a, 0x02, 0x08, 0x01, 0x12, 0x0b, 0x0a, 0x06, 0x44, 0x65, 0x65, 0x70, 0x41, 0x49, 0x10, + 0xed, 0x04, 0x12, 0x11, 0x0a, 0x0c, 0x4d, 0x65, 0x61, 0x6e, 0x69, 0x6e, 0x67, 0x43, 0x6c, 0x6f, + 0x75, 0x64, 0x10, 0xee, 0x04, 0x12, 0x10, 0x0a, 0x0b, 0x4e, 0x65, 0x75, 0x74, 0x72, 0x69, 0x6e, + 0x6f, 0x41, 0x70, 0x69, 0x10, 0xef, 0x04, 0x12, 0x0e, 0x0a, 0x09, 0x53, 0x74, 0x6f, 0x72, 0x65, + 0x63, 0x6f, 0x76, 0x65, 0x10, 0xf0, 0x04, 0x12, 0x0c, 0x0a, 0x07, 0x53, 0x68, 0x69, 0x70, 0x64, + 0x61, 0x79, 0x10, 0xf1, 0x04, 0x12, 0x0e, 0x0a, 0x09, 0x53, 0x65, 0x6e, 0x74, 0x69, 0x6d, 0x65, + 0x6e, 0x74, 0x10, 0xf2, 0x04, 0x12, 0x18, 0x0a, 0x13, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x43, + 0x68, 0x61, 0x74, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x69, 0x6e, 0x67, 0x10, 0xf3, 0x04, 0x12, + 0x10, 0x0a, 0x0b, 0x54, 0x65, 0x61, 0x6d, 0x77, 0x6f, 0x72, 0x6b, 0x43, 0x52, 0x4d, 0x10, 0xf4, + 0x04, 0x12, 0x11, 0x0a, 0x0c, 0x54, 0x65, 0x61, 0x6d, 0x77, 0x6f, 0x72, 0x6b, 0x44, 0x65, 0x73, + 0x6b, 0x10, 0xf5, 0x04, 0x12, 0x13, 0x0a, 0x0e, 0x54, 0x65, 0x61, 0x6d, 0x77, 0x6f, 0x72, 0x6b, + 0x53, 0x70, 0x61, 0x63, 0x65, 0x73, 0x10, 0xf6, 0x04, 0x12, 0x0f, 0x0a, 0x0a, 0x54, 0x68, 0x65, + 0x4f, 0x64, 0x64, 0x73, 0x41, 0x70, 0x69, 0x10, 0xf7, 0x04, 0x12, 0x0b, 0x0a, 0x06, 0x41, 0x70, + 0x61, 0x63, 0x74, 0x61, 0x10, 0xf8, 0x04, 0x12, 0x0f, 0x0a, 0x0a, 0x47, 0x65, 0x74, 0x53, 0x61, + 0x6e, 0x64, 0x62, 0x6f, 0x78, 0x10, 0xf9, 0x04, 0x12, 0x0e, 0x0a, 0x05, 0x48, 0x61, 0x70, 0x70, + 0x69, 0x10, 0xfa, 0x04, 0x1a, 0x02, 0x08, 0x01, 0x12, 0x0a, 0x0a, 0x05, 0x4f, 0x61, 0x6e, 0x64, 0x61, 0x10, 0xfb, 0x04, 0x12, 0x0e, 0x0a, 0x09, 0x46, 0x61, 0x73, 0x74, 0x46, 0x6f, 0x72, 0x65, 0x78, 0x10, 0xfc, 0x04, 0x12, 0x0d, 0x0a, 0x08, 0x41, 0x50, 0x49, 0x4d, 0x61, 0x74, 0x69, 0x63, 0x10, 0xfd, 0x04, 0x12, 0x0f, 0x0a, 0x0a, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x45, 0x79, @@ -4042,175 +4073,184 @@ var file_detectors_proto_rawDesc = []byte{ 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x54, 0x6f, 0x6f, 0x6c, 0x73, 0x10, 0x81, 0x06, 0x12, 0x0f, 0x0a, 0x0a, 0x43, 0x72, 0x61, 0x66, 0x74, 0x4d, 0x79, 0x50, 0x44, 0x46, 0x10, 0x82, 0x06, 0x12, 0x0e, 0x0a, 0x09, 0x45, 0x78, 0x70, 0x6f, 0x72, 0x74, 0x53, 0x44, 0x4b, 0x10, 0x83, 0x06, 0x12, - 0x11, 0x0a, 0x0c, 0x47, 0x6c, 0x69, 0x74, 0x74, 0x65, 0x72, 0x6c, 0x79, 0x41, 0x50, 0x49, 0x10, - 0x84, 0x06, 0x12, 0x0d, 0x0a, 0x08, 0x48, 0x79, 0x62, 0x69, 0x73, 0x63, 0x75, 0x73, 0x10, 0x85, - 0x06, 0x12, 0x09, 0x0a, 0x04, 0x4d, 0x69, 0x72, 0x6f, 0x10, 0x86, 0x06, 0x12, 0x0f, 0x0a, 0x0a, - 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x70, 0x61, 0x67, 0x65, 0x10, 0x87, 0x06, 0x12, 0x0e, 0x0a, - 0x09, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x70, 0x61, 0x6c, 0x10, 0x88, 0x06, 0x12, 0x0d, 0x0a, - 0x08, 0x54, 0x65, 0x6c, 0x65, 0x74, 0x79, 0x70, 0x65, 0x10, 0x89, 0x06, 0x12, 0x0d, 0x0a, 0x08, - 0x54, 0x69, 0x6d, 0x65, 0x43, 0x61, 0x6d, 0x70, 0x10, 0x8a, 0x06, 0x12, 0x0d, 0x0a, 0x08, 0x55, - 0x73, 0x65, 0x72, 0x66, 0x6c, 0x6f, 0x77, 0x10, 0x8b, 0x06, 0x12, 0x0b, 0x0a, 0x06, 0x57, 0x69, - 0x73, 0x74, 0x69, 0x61, 0x10, 0x8c, 0x06, 0x12, 0x0f, 0x0a, 0x0a, 0x53, 0x70, 0x6f, 0x72, 0x74, - 0x52, 0x61, 0x64, 0x61, 0x72, 0x10, 0x8d, 0x06, 0x12, 0x10, 0x0a, 0x0b, 0x55, 0x70, 0x74, 0x69, - 0x6d, 0x65, 0x52, 0x6f, 0x62, 0x6f, 0x74, 0x10, 0x8e, 0x06, 0x12, 0x0e, 0x0a, 0x09, 0x43, 0x6f, - 0x64, 0x65, 0x71, 0x75, 0x69, 0x72, 0x79, 0x10, 0x8f, 0x06, 0x12, 0x11, 0x0a, 0x0c, 0x45, 0x78, - 0x74, 0x72, 0x61, 0x63, 0x74, 0x6f, 0x72, 0x41, 0x50, 0x49, 0x10, 0x90, 0x06, 0x12, 0x0d, 0x0a, - 0x08, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x10, 0x91, 0x06, 0x12, 0x0e, 0x0a, 0x09, - 0x4d, 0x61, 0x67, 0x69, 0x63, 0x42, 0x65, 0x6c, 0x6c, 0x10, 0x92, 0x06, 0x12, 0x0f, 0x0a, 0x0a, - 0x53, 0x74, 0x6f, 0x72, 0x6d, 0x62, 0x6f, 0x61, 0x72, 0x64, 0x10, 0x93, 0x06, 0x12, 0x0d, 0x0a, - 0x08, 0x41, 0x70, 0x69, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x10, 0x94, 0x06, 0x12, 0x0b, 0x0a, 0x06, - 0x44, 0x69, 0x73, 0x71, 0x75, 0x73, 0x10, 0x95, 0x06, 0x12, 0x0b, 0x0a, 0x06, 0x57, 0x6f, 0x6f, - 0x70, 0x72, 0x61, 0x10, 0x96, 0x06, 0x12, 0x0e, 0x0a, 0x09, 0x50, 0x61, 0x70, 0x65, 0x72, 0x66, - 0x6f, 0x72, 0x6d, 0x10, 0x97, 0x06, 0x12, 0x0c, 0x0a, 0x07, 0x47, 0x75, 0x6d, 0x72, 0x6f, 0x61, - 0x64, 0x10, 0x98, 0x06, 0x12, 0x0f, 0x0a, 0x0a, 0x50, 0x61, 0x79, 0x64, 0x69, 0x72, 0x74, 0x61, - 0x70, 0x70, 0x10, 0x99, 0x06, 0x12, 0x0e, 0x0a, 0x09, 0x44, 0x65, 0x74, 0x65, 0x63, 0x74, 0x69, - 0x66, 0x79, 0x10, 0x9a, 0x06, 0x12, 0x0f, 0x0a, 0x0a, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x63, - 0x61, 0x6b, 0x65, 0x10, 0x9b, 0x06, 0x12, 0x0f, 0x0a, 0x0a, 0x4a, 0x75, 0x6d, 0x70, 0x73, 0x65, - 0x6c, 0x6c, 0x65, 0x72, 0x10, 0x9c, 0x06, 0x12, 0x0f, 0x0a, 0x0a, 0x4c, 0x75, 0x6e, 0x63, 0x68, - 0x4d, 0x6f, 0x6e, 0x65, 0x79, 0x10, 0x9d, 0x06, 0x12, 0x0c, 0x0a, 0x07, 0x52, 0x6f, 0x73, 0x65, - 0x74, 0x74, 0x65, 0x10, 0x9e, 0x06, 0x12, 0x09, 0x0a, 0x04, 0x59, 0x65, 0x6c, 0x70, 0x10, 0x9f, - 0x06, 0x12, 0x0a, 0x0a, 0x05, 0x41, 0x74, 0x65, 0x72, 0x61, 0x10, 0xa0, 0x06, 0x12, 0x12, 0x0a, - 0x0d, 0x45, 0x63, 0x6f, 0x53, 0x74, 0x72, 0x75, 0x78, 0x75, 0x72, 0x65, 0x49, 0x54, 0x10, 0xa1, - 0x06, 0x12, 0x08, 0x0a, 0x03, 0x41, 0x68, 0x61, 0x10, 0xa2, 0x06, 0x12, 0x0d, 0x0a, 0x08, 0x50, - 0x61, 0x72, 0x73, 0x65, 0x68, 0x75, 0x62, 0x10, 0xa3, 0x06, 0x12, 0x11, 0x0a, 0x0c, 0x50, 0x61, - 0x63, 0x6b, 0x61, 0x67, 0x65, 0x43, 0x6c, 0x6f, 0x75, 0x64, 0x10, 0xa4, 0x06, 0x12, 0x0f, 0x0a, - 0x0a, 0x43, 0x6c, 0x6f, 0x75, 0x64, 0x73, 0x6d, 0x69, 0x74, 0x68, 0x10, 0xa5, 0x06, 0x12, 0x0d, - 0x0a, 0x08, 0x46, 0x6c, 0x6f, 0x77, 0x64, 0x61, 0x73, 0x68, 0x10, 0xa6, 0x06, 0x12, 0x0d, 0x0a, - 0x08, 0x46, 0x6c, 0x6f, 0x77, 0x64, 0x6f, 0x63, 0x6b, 0x10, 0xa7, 0x06, 0x12, 0x0b, 0x0a, 0x06, - 0x46, 0x69, 0x62, 0x65, 0x72, 0x79, 0x10, 0xa8, 0x06, 0x12, 0x0d, 0x0a, 0x08, 0x54, 0x79, 0x70, - 0x65, 0x74, 0x61, 0x6c, 0x6b, 0x10, 0xa9, 0x06, 0x12, 0x0e, 0x0a, 0x09, 0x56, 0x6f, 0x6f, 0x64, - 0x6f, 0x6f, 0x53, 0x4d, 0x53, 0x10, 0xaa, 0x06, 0x12, 0x0e, 0x0a, 0x09, 0x5a, 0x75, 0x6c, 0x69, - 0x70, 0x43, 0x68, 0x61, 0x74, 0x10, 0xab, 0x06, 0x12, 0x0e, 0x0a, 0x09, 0x46, 0x6f, 0x72, 0x6d, - 0x63, 0x72, 0x61, 0x66, 0x74, 0x10, 0xac, 0x06, 0x12, 0x0c, 0x0a, 0x07, 0x49, 0x65, 0x78, 0x61, - 0x70, 0x69, 0x73, 0x10, 0xad, 0x06, 0x12, 0x0e, 0x0a, 0x09, 0x52, 0x65, 0x61, 0x63, 0x68, 0x6d, - 0x61, 0x69, 0x6c, 0x10, 0xae, 0x06, 0x12, 0x0f, 0x0a, 0x0a, 0x43, 0x68, 0x61, 0x72, 0x74, 0x6d, - 0x6f, 0x67, 0x75, 0x6c, 0x10, 0xaf, 0x06, 0x12, 0x0f, 0x0a, 0x0a, 0x41, 0x70, 0x70, 0x6f, 0x69, - 0x6e, 0x74, 0x65, 0x64, 0x64, 0x10, 0xb0, 0x06, 0x12, 0x08, 0x0a, 0x03, 0x57, 0x69, 0x74, 0x10, - 0xb1, 0x06, 0x12, 0x15, 0x0a, 0x10, 0x52, 0x65, 0x63, 0x68, 0x61, 0x72, 0x67, 0x65, 0x50, 0x61, - 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x10, 0xb2, 0x06, 0x12, 0x0f, 0x0a, 0x0a, 0x44, 0x69, 0x67, - 0x67, 0x65, 0x72, 0x6e, 0x61, 0x75, 0x74, 0x10, 0xb3, 0x06, 0x12, 0x10, 0x0a, 0x0b, 0x4d, 0x6f, - 0x6e, 0x6b, 0x65, 0x79, 0x4c, 0x65, 0x61, 0x72, 0x6e, 0x10, 0xb4, 0x06, 0x12, 0x0a, 0x0a, 0x05, - 0x44, 0x75, 0x70, 0x6c, 0x79, 0x10, 0xb5, 0x06, 0x12, 0x0e, 0x0a, 0x09, 0x50, 0x6f, 0x73, 0x74, - 0x62, 0x61, 0x63, 0x6b, 0x73, 0x10, 0xb6, 0x06, 0x12, 0x0d, 0x0a, 0x08, 0x43, 0x6f, 0x6c, 0x6c, - 0x65, 0x63, 0x74, 0x32, 0x10, 0xb7, 0x06, 0x12, 0x0c, 0x0a, 0x07, 0x5a, 0x65, 0x6e, 0x52, 0x6f, - 0x77, 0x73, 0x10, 0xb8, 0x06, 0x12, 0x10, 0x0a, 0x0b, 0x5a, 0x69, 0x70, 0x63, 0x6f, 0x64, 0x65, - 0x62, 0x61, 0x73, 0x65, 0x10, 0xb9, 0x06, 0x12, 0x0b, 0x0a, 0x06, 0x54, 0x65, 0x66, 0x74, 0x65, - 0x72, 0x10, 0xba, 0x06, 0x12, 0x0a, 0x0a, 0x05, 0x54, 0x77, 0x69, 0x73, 0x74, 0x10, 0xbb, 0x06, - 0x12, 0x16, 0x0a, 0x11, 0x42, 0x72, 0x61, 0x69, 0x6e, 0x74, 0x72, 0x65, 0x65, 0x50, 0x61, 0x79, - 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x10, 0xbc, 0x06, 0x12, 0x11, 0x0a, 0x0c, 0x43, 0x6c, 0x6f, 0x75, - 0x64, 0x43, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x74, 0x10, 0xbd, 0x06, 0x12, 0x0c, 0x0a, 0x07, 0x47, - 0x72, 0x61, 0x66, 0x61, 0x6e, 0x61, 0x10, 0xbe, 0x06, 0x12, 0x0f, 0x0a, 0x0a, 0x43, 0x6f, 0x6e, - 0x76, 0x65, 0x72, 0x74, 0x41, 0x70, 0x69, 0x10, 0xbf, 0x06, 0x12, 0x11, 0x0a, 0x0c, 0x54, 0x72, - 0x61, 0x6e, 0x73, 0x66, 0x65, 0x72, 0x77, 0x69, 0x73, 0x65, 0x10, 0xc0, 0x06, 0x12, 0x0c, 0x0a, - 0x07, 0x42, 0x75, 0x6c, 0x6b, 0x73, 0x6d, 0x73, 0x10, 0xc1, 0x06, 0x12, 0x0c, 0x0a, 0x07, 0x44, - 0x61, 0x74, 0x61, 0x62, 0x6f, 0x78, 0x10, 0xc2, 0x06, 0x12, 0x0e, 0x0a, 0x09, 0x4f, 0x6e, 0x65, - 0x73, 0x69, 0x67, 0x6e, 0x61, 0x6c, 0x10, 0xc3, 0x06, 0x12, 0x0c, 0x0a, 0x07, 0x52, 0x65, 0x6e, - 0x74, 0x6d, 0x61, 0x6e, 0x10, 0xc4, 0x06, 0x12, 0x0c, 0x0a, 0x07, 0x50, 0x61, 0x72, 0x73, 0x65, - 0x75, 0x72, 0x10, 0xc5, 0x06, 0x12, 0x0e, 0x0a, 0x09, 0x44, 0x6f, 0x63, 0x70, 0x61, 0x72, 0x73, - 0x65, 0x72, 0x10, 0xc6, 0x06, 0x12, 0x0d, 0x0a, 0x08, 0x46, 0x6f, 0x72, 0x6d, 0x73, 0x69, 0x74, - 0x65, 0x10, 0xc7, 0x06, 0x12, 0x11, 0x0a, 0x0c, 0x54, 0x69, 0x63, 0x6b, 0x65, 0x74, 0x74, 0x61, - 0x69, 0x6c, 0x6f, 0x72, 0x10, 0xc8, 0x06, 0x12, 0x0c, 0x0a, 0x07, 0x4c, 0x65, 0x6d, 0x6c, 0x69, - 0x73, 0x74, 0x10, 0xc9, 0x06, 0x12, 0x0c, 0x0a, 0x07, 0x50, 0x72, 0x6f, 0x64, 0x70, 0x61, 0x64, - 0x10, 0xca, 0x06, 0x12, 0x0e, 0x0a, 0x09, 0x46, 0x6f, 0x72, 0x6d, 0x73, 0x74, 0x61, 0x63, 0x6b, - 0x10, 0xcb, 0x06, 0x12, 0x10, 0x0a, 0x0b, 0x43, 0x6f, 0x64, 0x65, 0x63, 0x6c, 0x69, 0x6d, 0x61, - 0x74, 0x65, 0x10, 0xcc, 0x06, 0x12, 0x0e, 0x0a, 0x09, 0x43, 0x6f, 0x64, 0x65, 0x6d, 0x61, 0x67, - 0x69, 0x63, 0x10, 0xcd, 0x06, 0x12, 0x0a, 0x0a, 0x05, 0x56, 0x62, 0x6f, 0x75, 0x74, 0x10, 0xce, - 0x06, 0x12, 0x0e, 0x0a, 0x09, 0x4e, 0x69, 0x67, 0x68, 0x74, 0x66, 0x61, 0x6c, 0x6c, 0x10, 0xcf, - 0x06, 0x12, 0x0f, 0x0a, 0x0a, 0x46, 0x6c, 0x69, 0x67, 0x68, 0x74, 0x4c, 0x61, 0x62, 0x73, 0x10, - 0xd0, 0x06, 0x12, 0x11, 0x0a, 0x0c, 0x53, 0x70, 0x65, 0x65, 0x63, 0x68, 0x54, 0x65, 0x78, 0x74, - 0x41, 0x49, 0x10, 0xd1, 0x06, 0x12, 0x0d, 0x0a, 0x08, 0x50, 0x6f, 0x6c, 0x6c, 0x73, 0x41, 0x50, - 0x49, 0x10, 0xd2, 0x06, 0x12, 0x0b, 0x0a, 0x06, 0x53, 0x69, 0x6d, 0x46, 0x69, 0x6e, 0x10, 0xd3, - 0x06, 0x12, 0x0a, 0x0a, 0x05, 0x53, 0x63, 0x61, 0x6c, 0x72, 0x10, 0xd4, 0x06, 0x12, 0x0f, 0x0a, - 0x0a, 0x4b, 0x61, 0x6e, 0x62, 0x61, 0x6e, 0x74, 0x6f, 0x6f, 0x6c, 0x10, 0xd5, 0x06, 0x12, 0x10, - 0x0a, 0x0b, 0x42, 0x72, 0x69, 0x67, 0x68, 0x74, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x10, 0xd6, 0x06, - 0x12, 0x0c, 0x0a, 0x07, 0x48, 0x6f, 0x74, 0x77, 0x69, 0x72, 0x65, 0x10, 0xd7, 0x06, 0x12, 0x0d, - 0x0a, 0x08, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x62, 0x6f, 0x74, 0x10, 0xd8, 0x06, 0x12, 0x0c, 0x0a, - 0x07, 0x54, 0x69, 0x6d, 0x65, 0x6b, 0x69, 0x74, 0x10, 0xd9, 0x06, 0x12, 0x10, 0x0a, 0x0b, 0x49, - 0x6e, 0x74, 0x65, 0x72, 0x73, 0x65, 0x6c, 0x6c, 0x65, 0x72, 0x10, 0xda, 0x06, 0x12, 0x11, 0x0a, - 0x0c, 0x4d, 0x6f, 0x6a, 0x6f, 0x68, 0x65, 0x6c, 0x70, 0x64, 0x65, 0x73, 0x6b, 0x10, 0xdb, 0x06, - 0x12, 0x0f, 0x0a, 0x0a, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x73, 0x65, 0x6e, 0x64, 0x10, 0xdc, - 0x06, 0x12, 0x10, 0x0a, 0x0b, 0x47, 0x65, 0x74, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x10, 0xdd, 0x06, 0x12, 0x0c, 0x0a, 0x07, 0x44, 0x79, 0x6e, 0x61, 0x64, 0x6f, 0x74, 0x10, 0xde, - 0x06, 0x12, 0x0a, 0x0a, 0x05, 0x44, 0x65, 0x6d, 0x69, 0x6f, 0x10, 0xdf, 0x06, 0x12, 0x0b, 0x0a, - 0x06, 0x54, 0x6f, 0x6b, 0x65, 0x65, 0x74, 0x10, 0xe0, 0x06, 0x12, 0x11, 0x0a, 0x0c, 0x4d, 0x79, - 0x65, 0x78, 0x70, 0x65, 0x72, 0x69, 0x6d, 0x65, 0x6e, 0x74, 0x10, 0xe1, 0x06, 0x12, 0x0e, 0x0a, - 0x09, 0x43, 0x6f, 0x70, 0x79, 0x73, 0x63, 0x61, 0x70, 0x65, 0x10, 0xe2, 0x06, 0x12, 0x0d, 0x0a, - 0x08, 0x42, 0x65, 0x73, 0x6e, 0x61, 0x70, 0x70, 0x79, 0x10, 0xe3, 0x06, 0x12, 0x0e, 0x0a, 0x09, - 0x53, 0x61, 0x6c, 0x65, 0x73, 0x6d, 0x61, 0x74, 0x65, 0x10, 0xe4, 0x06, 0x12, 0x0f, 0x0a, 0x0a, - 0x48, 0x65, 0x61, 0x74, 0x6d, 0x61, 0x70, 0x61, 0x70, 0x69, 0x10, 0xe5, 0x06, 0x12, 0x11, 0x0a, - 0x0c, 0x57, 0x65, 0x62, 0x73, 0x69, 0x74, 0x65, 0x70, 0x75, 0x6c, 0x73, 0x65, 0x10, 0xe6, 0x06, - 0x12, 0x0e, 0x0a, 0x09, 0x55, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x69, 0x66, 0x79, 0x10, 0xe7, 0x06, - 0x12, 0x0c, 0x0a, 0x07, 0x43, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x74, 0x10, 0xe8, 0x06, 0x12, 0x0d, - 0x0a, 0x08, 0x50, 0x44, 0x46, 0x6d, 0x79, 0x55, 0x52, 0x4c, 0x10, 0xe9, 0x06, 0x12, 0x10, 0x0a, - 0x0b, 0x41, 0x70, 0x69, 0x32, 0x43, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x74, 0x10, 0xea, 0x06, 0x12, - 0x0d, 0x0a, 0x08, 0x4f, 0x70, 0x73, 0x67, 0x65, 0x6e, 0x69, 0x65, 0x10, 0xeb, 0x06, 0x12, 0x0b, - 0x0a, 0x06, 0x47, 0x65, 0x6d, 0x69, 0x6e, 0x69, 0x10, 0xec, 0x06, 0x12, 0x0e, 0x0a, 0x09, 0x48, - 0x6f, 0x6e, 0x65, 0x79, 0x63, 0x6f, 0x6d, 0x62, 0x10, 0xed, 0x06, 0x12, 0x14, 0x0a, 0x0f, 0x4b, - 0x61, 0x6c, 0x74, 0x75, 0x72, 0x61, 0x41, 0x70, 0x70, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x10, 0xee, - 0x06, 0x12, 0x13, 0x0a, 0x0e, 0x4b, 0x61, 0x6c, 0x74, 0x75, 0x72, 0x61, 0x53, 0x65, 0x73, 0x73, - 0x69, 0x6f, 0x6e, 0x10, 0xef, 0x06, 0x12, 0x0a, 0x0a, 0x05, 0x42, 0x69, 0x74, 0x47, 0x6f, 0x10, - 0xf0, 0x06, 0x12, 0x0d, 0x0a, 0x08, 0x4f, 0x70, 0x74, 0x69, 0x64, 0x61, 0x73, 0x68, 0x10, 0xf1, - 0x06, 0x12, 0x0a, 0x0a, 0x05, 0x49, 0x6d, 0x67, 0x69, 0x78, 0x10, 0xf2, 0x06, 0x12, 0x10, 0x0a, - 0x0b, 0x49, 0x6d, 0x61, 0x67, 0x65, 0x54, 0x6f, 0x54, 0x65, 0x78, 0x74, 0x10, 0xf3, 0x06, 0x12, - 0x10, 0x0a, 0x0b, 0x50, 0x61, 0x67, 0x65, 0x32, 0x49, 0x6d, 0x61, 0x67, 0x65, 0x73, 0x10, 0xf4, - 0x06, 0x12, 0x0e, 0x0a, 0x09, 0x51, 0x75, 0x69, 0x63, 0x6b, 0x62, 0x61, 0x73, 0x65, 0x10, 0xf5, - 0x06, 0x12, 0x0d, 0x0a, 0x08, 0x52, 0x65, 0x64, 0x62, 0x6f, 0x6f, 0x74, 0x68, 0x10, 0xf6, 0x06, - 0x12, 0x0b, 0x0a, 0x06, 0x4e, 0x75, 0x62, 0x65, 0x6c, 0x61, 0x10, 0xf7, 0x06, 0x12, 0x0c, 0x0a, - 0x07, 0x49, 0x6e, 0x66, 0x6f, 0x62, 0x69, 0x70, 0x10, 0xf8, 0x06, 0x12, 0x0a, 0x0a, 0x05, 0x55, - 0x70, 0x72, 0x6f, 0x63, 0x10, 0xf9, 0x06, 0x12, 0x0f, 0x0a, 0x0a, 0x53, 0x75, 0x70, 0x70, 0x6f, - 0x72, 0x74, 0x62, 0x65, 0x65, 0x10, 0xfa, 0x06, 0x12, 0x0e, 0x0a, 0x09, 0x41, 0x66, 0x74, 0x65, - 0x72, 0x73, 0x68, 0x69, 0x70, 0x10, 0xfb, 0x06, 0x12, 0x0c, 0x0a, 0x07, 0x45, 0x64, 0x75, 0x73, - 0x69, 0x67, 0x6e, 0x10, 0xfc, 0x06, 0x12, 0x0b, 0x0a, 0x06, 0x54, 0x65, 0x61, 0x6d, 0x75, 0x70, - 0x10, 0xfd, 0x06, 0x12, 0x0c, 0x0a, 0x07, 0x57, 0x6f, 0x72, 0x6b, 0x64, 0x61, 0x79, 0x10, 0xfe, - 0x06, 0x12, 0x0c, 0x0a, 0x07, 0x4d, 0x6f, 0x6e, 0x67, 0x6f, 0x44, 0x42, 0x10, 0xff, 0x06, 0x12, - 0x08, 0x0a, 0x03, 0x4e, 0x47, 0x43, 0x10, 0x80, 0x07, 0x12, 0x13, 0x0a, 0x0e, 0x44, 0x69, 0x67, - 0x69, 0x74, 0x61, 0x6c, 0x4f, 0x63, 0x65, 0x61, 0x6e, 0x56, 0x32, 0x10, 0x81, 0x07, 0x12, 0x0e, - 0x0a, 0x09, 0x53, 0x51, 0x4c, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x10, 0x82, 0x07, 0x12, 0x08, - 0x0a, 0x03, 0x46, 0x54, 0x50, 0x10, 0x83, 0x07, 0x12, 0x0a, 0x0a, 0x05, 0x52, 0x65, 0x64, 0x69, - 0x73, 0x10, 0x84, 0x07, 0x12, 0x09, 0x0a, 0x04, 0x4c, 0x44, 0x41, 0x50, 0x10, 0x85, 0x07, 0x12, - 0x0c, 0x0a, 0x07, 0x53, 0x68, 0x6f, 0x70, 0x69, 0x66, 0x79, 0x10, 0x86, 0x07, 0x12, 0x0d, 0x0a, - 0x08, 0x52, 0x61, 0x62, 0x62, 0x69, 0x74, 0x4d, 0x51, 0x10, 0x87, 0x07, 0x12, 0x10, 0x0a, 0x0b, - 0x43, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x52, 0x65, 0x67, 0x65, 0x78, 0x10, 0x88, 0x07, 0x12, 0x0e, - 0x0a, 0x09, 0x45, 0x74, 0x68, 0x65, 0x72, 0x73, 0x63, 0x61, 0x6e, 0x10, 0x89, 0x07, 0x12, 0x0b, - 0x0a, 0x06, 0x49, 0x6e, 0x66, 0x75, 0x72, 0x61, 0x10, 0x8a, 0x07, 0x12, 0x0c, 0x0a, 0x07, 0x41, - 0x6c, 0x63, 0x68, 0x65, 0x6d, 0x79, 0x10, 0x8b, 0x07, 0x12, 0x10, 0x0a, 0x0b, 0x42, 0x6c, 0x6f, - 0x63, 0x6b, 0x4e, 0x61, 0x74, 0x69, 0x76, 0x65, 0x10, 0x8c, 0x07, 0x12, 0x0c, 0x0a, 0x07, 0x4d, - 0x6f, 0x72, 0x61, 0x6c, 0x69, 0x73, 0x10, 0x8d, 0x07, 0x12, 0x0c, 0x0a, 0x07, 0x42, 0x73, 0x63, - 0x53, 0x63, 0x61, 0x6e, 0x10, 0x8e, 0x07, 0x12, 0x12, 0x0a, 0x0d, 0x43, 0x6f, 0x69, 0x6e, 0x4d, - 0x61, 0x72, 0x6b, 0x65, 0x74, 0x43, 0x61, 0x70, 0x10, 0x8f, 0x07, 0x12, 0x0a, 0x0a, 0x05, 0x50, - 0x65, 0x72, 0x63, 0x79, 0x10, 0x90, 0x07, 0x12, 0x11, 0x0a, 0x0c, 0x54, 0x69, 0x6e, 0x65, 0x73, - 0x57, 0x65, 0x62, 0x68, 0x6f, 0x6f, 0x6b, 0x10, 0x91, 0x07, 0x12, 0x0b, 0x0a, 0x06, 0x50, 0x75, - 0x6c, 0x75, 0x6d, 0x69, 0x10, 0x92, 0x07, 0x12, 0x12, 0x0a, 0x0d, 0x53, 0x75, 0x70, 0x61, 0x62, - 0x61, 0x73, 0x65, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x10, 0x93, 0x07, 0x12, 0x10, 0x0a, 0x0b, 0x4e, - 0x75, 0x47, 0x65, 0x74, 0x41, 0x70, 0x69, 0x4b, 0x65, 0x79, 0x10, 0x94, 0x07, 0x12, 0x0a, 0x0a, - 0x05, 0x41, 0x69, 0x76, 0x65, 0x6e, 0x10, 0x95, 0x07, 0x12, 0x0c, 0x0a, 0x07, 0x50, 0x72, 0x65, - 0x66, 0x65, 0x63, 0x74, 0x10, 0x96, 0x07, 0x12, 0x0d, 0x0a, 0x08, 0x44, 0x6f, 0x63, 0x75, 0x73, - 0x69, 0x67, 0x6e, 0x10, 0x97, 0x07, 0x12, 0x0e, 0x0a, 0x09, 0x43, 0x6f, 0x75, 0x63, 0x68, 0x62, - 0x61, 0x73, 0x65, 0x10, 0x98, 0x07, 0x12, 0x0e, 0x0a, 0x09, 0x44, 0x6f, 0x63, 0x6b, 0x65, 0x72, - 0x68, 0x75, 0x62, 0x10, 0x99, 0x07, 0x12, 0x19, 0x0a, 0x14, 0x54, 0x72, 0x75, 0x66, 0x66, 0x6c, - 0x65, 0x68, 0x6f, 0x67, 0x45, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x69, 0x73, 0x65, 0x10, 0x9a, - 0x07, 0x12, 0x10, 0x0a, 0x0b, 0x45, 0x6e, 0x76, 0x6f, 0x79, 0x41, 0x70, 0x69, 0x4b, 0x65, 0x79, - 0x10, 0x9b, 0x07, 0x12, 0x11, 0x0a, 0x0c, 0x47, 0x69, 0x74, 0x48, 0x75, 0x62, 0x4f, 0x61, 0x75, - 0x74, 0x68, 0x32, 0x10, 0x9c, 0x07, 0x12, 0x0f, 0x0a, 0x0a, 0x53, 0x61, 0x6c, 0x65, 0x73, 0x66, - 0x6f, 0x72, 0x63, 0x65, 0x10, 0x9d, 0x07, 0x12, 0x10, 0x0a, 0x0b, 0x48, 0x75, 0x67, 0x67, 0x69, - 0x6e, 0x67, 0x46, 0x61, 0x63, 0x65, 0x10, 0x9e, 0x07, 0x12, 0x0e, 0x0a, 0x09, 0x53, 0x6e, 0x6f, - 0x77, 0x66, 0x6c, 0x61, 0x6b, 0x65, 0x10, 0x9f, 0x07, 0x12, 0x10, 0x0a, 0x0b, 0x53, 0x6f, 0x75, - 0x72, 0x63, 0x65, 0x67, 0x72, 0x61, 0x70, 0x68, 0x10, 0xa0, 0x07, 0x12, 0x0e, 0x0a, 0x09, 0x54, - 0x61, 0x69, 0x6c, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x10, 0xa1, 0x07, 0x12, 0x10, 0x0a, 0x0b, 0x57, - 0x65, 0x62, 0x33, 0x53, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x10, 0xa2, 0x07, 0x12, 0x11, 0x0a, - 0x0c, 0x41, 0x7a, 0x75, 0x72, 0x65, 0x53, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x10, 0xa3, 0x07, - 0x12, 0x12, 0x0a, 0x0d, 0x50, 0x6c, 0x61, 0x6e, 0x65, 0x74, 0x53, 0x63, 0x61, 0x6c, 0x65, 0x44, - 0x62, 0x10, 0xa4, 0x07, 0x12, 0x0e, 0x0a, 0x09, 0x41, 0x6e, 0x74, 0x68, 0x72, 0x6f, 0x70, 0x69, - 0x63, 0x10, 0xa5, 0x07, 0x12, 0x09, 0x0a, 0x04, 0x52, 0x61, 0x6d, 0x70, 0x10, 0xa6, 0x07, 0x12, - 0x0c, 0x0a, 0x07, 0x4b, 0x6c, 0x61, 0x76, 0x69, 0x79, 0x6f, 0x10, 0xa7, 0x07, 0x12, 0x14, 0x0a, - 0x0f, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x67, 0x72, 0x61, 0x70, 0x68, 0x43, 0x6f, 0x64, 0x79, - 0x10, 0xa8, 0x07, 0x12, 0x0e, 0x0a, 0x09, 0x56, 0x6f, 0x69, 0x63, 0x65, 0x66, 0x6c, 0x6f, 0x77, - 0x10, 0xa9, 0x07, 0x12, 0x0c, 0x0a, 0x07, 0x50, 0x72, 0x69, 0x76, 0x61, 0x63, 0x79, 0x10, 0xaa, - 0x07, 0x42, 0x3d, 0x5a, 0x3b, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, - 0x74, 0x72, 0x75, 0x66, 0x66, 0x6c, 0x65, 0x73, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x2f, - 0x74, 0x72, 0x75, 0x66, 0x66, 0x6c, 0x65, 0x68, 0x6f, 0x67, 0x2f, 0x76, 0x33, 0x2f, 0x70, 0x6b, - 0x67, 0x2f, 0x70, 0x62, 0x2f, 0x64, 0x65, 0x74, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x73, 0x70, 0x62, - 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x15, 0x0a, 0x0c, 0x47, 0x6c, 0x69, 0x74, 0x74, 0x65, 0x72, 0x6c, 0x79, 0x41, 0x50, 0x49, 0x10, + 0x84, 0x06, 0x1a, 0x02, 0x08, 0x01, 0x12, 0x0d, 0x0a, 0x08, 0x48, 0x79, 0x62, 0x69, 0x73, 0x63, + 0x75, 0x73, 0x10, 0x85, 0x06, 0x12, 0x09, 0x0a, 0x04, 0x4d, 0x69, 0x72, 0x6f, 0x10, 0x86, 0x06, + 0x12, 0x0f, 0x0a, 0x0a, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x70, 0x61, 0x67, 0x65, 0x10, 0x87, + 0x06, 0x12, 0x0e, 0x0a, 0x09, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x70, 0x61, 0x6c, 0x10, 0x88, + 0x06, 0x12, 0x0d, 0x0a, 0x08, 0x54, 0x65, 0x6c, 0x65, 0x74, 0x79, 0x70, 0x65, 0x10, 0x89, 0x06, + 0x12, 0x0d, 0x0a, 0x08, 0x54, 0x69, 0x6d, 0x65, 0x43, 0x61, 0x6d, 0x70, 0x10, 0x8a, 0x06, 0x12, + 0x0d, 0x0a, 0x08, 0x55, 0x73, 0x65, 0x72, 0x66, 0x6c, 0x6f, 0x77, 0x10, 0x8b, 0x06, 0x12, 0x0b, + 0x0a, 0x06, 0x57, 0x69, 0x73, 0x74, 0x69, 0x61, 0x10, 0x8c, 0x06, 0x12, 0x0f, 0x0a, 0x0a, 0x53, + 0x70, 0x6f, 0x72, 0x74, 0x52, 0x61, 0x64, 0x61, 0x72, 0x10, 0x8d, 0x06, 0x12, 0x10, 0x0a, 0x0b, + 0x55, 0x70, 0x74, 0x69, 0x6d, 0x65, 0x52, 0x6f, 0x62, 0x6f, 0x74, 0x10, 0x8e, 0x06, 0x12, 0x0e, + 0x0a, 0x09, 0x43, 0x6f, 0x64, 0x65, 0x71, 0x75, 0x69, 0x72, 0x79, 0x10, 0x8f, 0x06, 0x12, 0x11, + 0x0a, 0x0c, 0x45, 0x78, 0x74, 0x72, 0x61, 0x63, 0x74, 0x6f, 0x72, 0x41, 0x50, 0x49, 0x10, 0x90, + 0x06, 0x12, 0x0d, 0x0a, 0x08, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x10, 0x91, 0x06, + 0x12, 0x0e, 0x0a, 0x09, 0x4d, 0x61, 0x67, 0x69, 0x63, 0x42, 0x65, 0x6c, 0x6c, 0x10, 0x92, 0x06, + 0x12, 0x0f, 0x0a, 0x0a, 0x53, 0x74, 0x6f, 0x72, 0x6d, 0x62, 0x6f, 0x61, 0x72, 0x64, 0x10, 0x93, + 0x06, 0x12, 0x0d, 0x0a, 0x08, 0x41, 0x70, 0x69, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x10, 0x94, 0x06, + 0x12, 0x0b, 0x0a, 0x06, 0x44, 0x69, 0x73, 0x71, 0x75, 0x73, 0x10, 0x95, 0x06, 0x12, 0x0b, 0x0a, + 0x06, 0x57, 0x6f, 0x6f, 0x70, 0x72, 0x61, 0x10, 0x96, 0x06, 0x12, 0x0e, 0x0a, 0x09, 0x50, 0x61, + 0x70, 0x65, 0x72, 0x66, 0x6f, 0x72, 0x6d, 0x10, 0x97, 0x06, 0x12, 0x0c, 0x0a, 0x07, 0x47, 0x75, + 0x6d, 0x72, 0x6f, 0x61, 0x64, 0x10, 0x98, 0x06, 0x12, 0x0f, 0x0a, 0x0a, 0x50, 0x61, 0x79, 0x64, + 0x69, 0x72, 0x74, 0x61, 0x70, 0x70, 0x10, 0x99, 0x06, 0x12, 0x0e, 0x0a, 0x09, 0x44, 0x65, 0x74, + 0x65, 0x63, 0x74, 0x69, 0x66, 0x79, 0x10, 0x9a, 0x06, 0x12, 0x0f, 0x0a, 0x0a, 0x53, 0x74, 0x61, + 0x74, 0x75, 0x73, 0x63, 0x61, 0x6b, 0x65, 0x10, 0x9b, 0x06, 0x12, 0x0f, 0x0a, 0x0a, 0x4a, 0x75, + 0x6d, 0x70, 0x73, 0x65, 0x6c, 0x6c, 0x65, 0x72, 0x10, 0x9c, 0x06, 0x12, 0x0f, 0x0a, 0x0a, 0x4c, + 0x75, 0x6e, 0x63, 0x68, 0x4d, 0x6f, 0x6e, 0x65, 0x79, 0x10, 0x9d, 0x06, 0x12, 0x0c, 0x0a, 0x07, + 0x52, 0x6f, 0x73, 0x65, 0x74, 0x74, 0x65, 0x10, 0x9e, 0x06, 0x12, 0x09, 0x0a, 0x04, 0x59, 0x65, + 0x6c, 0x70, 0x10, 0x9f, 0x06, 0x12, 0x0a, 0x0a, 0x05, 0x41, 0x74, 0x65, 0x72, 0x61, 0x10, 0xa0, + 0x06, 0x12, 0x12, 0x0a, 0x0d, 0x45, 0x63, 0x6f, 0x53, 0x74, 0x72, 0x75, 0x78, 0x75, 0x72, 0x65, + 0x49, 0x54, 0x10, 0xa1, 0x06, 0x12, 0x08, 0x0a, 0x03, 0x41, 0x68, 0x61, 0x10, 0xa2, 0x06, 0x12, + 0x0d, 0x0a, 0x08, 0x50, 0x61, 0x72, 0x73, 0x65, 0x68, 0x75, 0x62, 0x10, 0xa3, 0x06, 0x12, 0x11, + 0x0a, 0x0c, 0x50, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x43, 0x6c, 0x6f, 0x75, 0x64, 0x10, 0xa4, + 0x06, 0x12, 0x0f, 0x0a, 0x0a, 0x43, 0x6c, 0x6f, 0x75, 0x64, 0x73, 0x6d, 0x69, 0x74, 0x68, 0x10, + 0xa5, 0x06, 0x12, 0x0d, 0x0a, 0x08, 0x46, 0x6c, 0x6f, 0x77, 0x64, 0x61, 0x73, 0x68, 0x10, 0xa6, + 0x06, 0x12, 0x11, 0x0a, 0x08, 0x46, 0x6c, 0x6f, 0x77, 0x64, 0x6f, 0x63, 0x6b, 0x10, 0xa7, 0x06, + 0x1a, 0x02, 0x08, 0x01, 0x12, 0x0b, 0x0a, 0x06, 0x46, 0x69, 0x62, 0x65, 0x72, 0x79, 0x10, 0xa8, + 0x06, 0x12, 0x0d, 0x0a, 0x08, 0x54, 0x79, 0x70, 0x65, 0x74, 0x61, 0x6c, 0x6b, 0x10, 0xa9, 0x06, + 0x12, 0x0e, 0x0a, 0x09, 0x56, 0x6f, 0x6f, 0x64, 0x6f, 0x6f, 0x53, 0x4d, 0x53, 0x10, 0xaa, 0x06, + 0x12, 0x0e, 0x0a, 0x09, 0x5a, 0x75, 0x6c, 0x69, 0x70, 0x43, 0x68, 0x61, 0x74, 0x10, 0xab, 0x06, + 0x12, 0x0e, 0x0a, 0x09, 0x46, 0x6f, 0x72, 0x6d, 0x63, 0x72, 0x61, 0x66, 0x74, 0x10, 0xac, 0x06, + 0x12, 0x0c, 0x0a, 0x07, 0x49, 0x65, 0x78, 0x61, 0x70, 0x69, 0x73, 0x10, 0xad, 0x06, 0x12, 0x0e, + 0x0a, 0x09, 0x52, 0x65, 0x61, 0x63, 0x68, 0x6d, 0x61, 0x69, 0x6c, 0x10, 0xae, 0x06, 0x12, 0x0f, + 0x0a, 0x0a, 0x43, 0x68, 0x61, 0x72, 0x74, 0x6d, 0x6f, 0x67, 0x75, 0x6c, 0x10, 0xaf, 0x06, 0x12, + 0x0f, 0x0a, 0x0a, 0x41, 0x70, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x65, 0x64, 0x64, 0x10, 0xb0, 0x06, + 0x12, 0x08, 0x0a, 0x03, 0x57, 0x69, 0x74, 0x10, 0xb1, 0x06, 0x12, 0x15, 0x0a, 0x10, 0x52, 0x65, + 0x63, 0x68, 0x61, 0x72, 0x67, 0x65, 0x50, 0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x10, 0xb2, + 0x06, 0x12, 0x0f, 0x0a, 0x0a, 0x44, 0x69, 0x67, 0x67, 0x65, 0x72, 0x6e, 0x61, 0x75, 0x74, 0x10, + 0xb3, 0x06, 0x12, 0x10, 0x0a, 0x0b, 0x4d, 0x6f, 0x6e, 0x6b, 0x65, 0x79, 0x4c, 0x65, 0x61, 0x72, + 0x6e, 0x10, 0xb4, 0x06, 0x12, 0x0a, 0x0a, 0x05, 0x44, 0x75, 0x70, 0x6c, 0x79, 0x10, 0xb5, 0x06, + 0x12, 0x0e, 0x0a, 0x09, 0x50, 0x6f, 0x73, 0x74, 0x62, 0x61, 0x63, 0x6b, 0x73, 0x10, 0xb6, 0x06, + 0x12, 0x0d, 0x0a, 0x08, 0x43, 0x6f, 0x6c, 0x6c, 0x65, 0x63, 0x74, 0x32, 0x10, 0xb7, 0x06, 0x12, + 0x0c, 0x0a, 0x07, 0x5a, 0x65, 0x6e, 0x52, 0x6f, 0x77, 0x73, 0x10, 0xb8, 0x06, 0x12, 0x10, 0x0a, + 0x0b, 0x5a, 0x69, 0x70, 0x63, 0x6f, 0x64, 0x65, 0x62, 0x61, 0x73, 0x65, 0x10, 0xb9, 0x06, 0x12, + 0x0b, 0x0a, 0x06, 0x54, 0x65, 0x66, 0x74, 0x65, 0x72, 0x10, 0xba, 0x06, 0x12, 0x0a, 0x0a, 0x05, + 0x54, 0x77, 0x69, 0x73, 0x74, 0x10, 0xbb, 0x06, 0x12, 0x16, 0x0a, 0x11, 0x42, 0x72, 0x61, 0x69, + 0x6e, 0x74, 0x72, 0x65, 0x65, 0x50, 0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x10, 0xbc, 0x06, + 0x12, 0x11, 0x0a, 0x0c, 0x43, 0x6c, 0x6f, 0x75, 0x64, 0x43, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x74, + 0x10, 0xbd, 0x06, 0x12, 0x0c, 0x0a, 0x07, 0x47, 0x72, 0x61, 0x66, 0x61, 0x6e, 0x61, 0x10, 0xbe, + 0x06, 0x12, 0x0f, 0x0a, 0x0a, 0x43, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x74, 0x41, 0x70, 0x69, 0x10, + 0xbf, 0x06, 0x12, 0x11, 0x0a, 0x0c, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x66, 0x65, 0x72, 0x77, 0x69, + 0x73, 0x65, 0x10, 0xc0, 0x06, 0x12, 0x0c, 0x0a, 0x07, 0x42, 0x75, 0x6c, 0x6b, 0x73, 0x6d, 0x73, + 0x10, 0xc1, 0x06, 0x12, 0x0c, 0x0a, 0x07, 0x44, 0x61, 0x74, 0x61, 0x62, 0x6f, 0x78, 0x10, 0xc2, + 0x06, 0x12, 0x0e, 0x0a, 0x09, 0x4f, 0x6e, 0x65, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x6c, 0x10, 0xc3, + 0x06, 0x12, 0x0c, 0x0a, 0x07, 0x52, 0x65, 0x6e, 0x74, 0x6d, 0x61, 0x6e, 0x10, 0xc4, 0x06, 0x12, + 0x0c, 0x0a, 0x07, 0x50, 0x61, 0x72, 0x73, 0x65, 0x75, 0x72, 0x10, 0xc5, 0x06, 0x12, 0x0e, 0x0a, + 0x09, 0x44, 0x6f, 0x63, 0x70, 0x61, 0x72, 0x73, 0x65, 0x72, 0x10, 0xc6, 0x06, 0x12, 0x0d, 0x0a, + 0x08, 0x46, 0x6f, 0x72, 0x6d, 0x73, 0x69, 0x74, 0x65, 0x10, 0xc7, 0x06, 0x12, 0x11, 0x0a, 0x0c, + 0x54, 0x69, 0x63, 0x6b, 0x65, 0x74, 0x74, 0x61, 0x69, 0x6c, 0x6f, 0x72, 0x10, 0xc8, 0x06, 0x12, + 0x0c, 0x0a, 0x07, 0x4c, 0x65, 0x6d, 0x6c, 0x69, 0x73, 0x74, 0x10, 0xc9, 0x06, 0x12, 0x0c, 0x0a, + 0x07, 0x50, 0x72, 0x6f, 0x64, 0x70, 0x61, 0x64, 0x10, 0xca, 0x06, 0x12, 0x0e, 0x0a, 0x09, 0x46, + 0x6f, 0x72, 0x6d, 0x73, 0x74, 0x61, 0x63, 0x6b, 0x10, 0xcb, 0x06, 0x12, 0x10, 0x0a, 0x0b, 0x43, + 0x6f, 0x64, 0x65, 0x63, 0x6c, 0x69, 0x6d, 0x61, 0x74, 0x65, 0x10, 0xcc, 0x06, 0x12, 0x0e, 0x0a, + 0x09, 0x43, 0x6f, 0x64, 0x65, 0x6d, 0x61, 0x67, 0x69, 0x63, 0x10, 0xcd, 0x06, 0x12, 0x0a, 0x0a, + 0x05, 0x56, 0x62, 0x6f, 0x75, 0x74, 0x10, 0xce, 0x06, 0x12, 0x0e, 0x0a, 0x09, 0x4e, 0x69, 0x67, + 0x68, 0x74, 0x66, 0x61, 0x6c, 0x6c, 0x10, 0xcf, 0x06, 0x12, 0x0f, 0x0a, 0x0a, 0x46, 0x6c, 0x69, + 0x67, 0x68, 0x74, 0x4c, 0x61, 0x62, 0x73, 0x10, 0xd0, 0x06, 0x12, 0x11, 0x0a, 0x0c, 0x53, 0x70, + 0x65, 0x65, 0x63, 0x68, 0x54, 0x65, 0x78, 0x74, 0x41, 0x49, 0x10, 0xd1, 0x06, 0x12, 0x0d, 0x0a, + 0x08, 0x50, 0x6f, 0x6c, 0x6c, 0x73, 0x41, 0x50, 0x49, 0x10, 0xd2, 0x06, 0x12, 0x0b, 0x0a, 0x06, + 0x53, 0x69, 0x6d, 0x46, 0x69, 0x6e, 0x10, 0xd3, 0x06, 0x12, 0x0a, 0x0a, 0x05, 0x53, 0x63, 0x61, + 0x6c, 0x72, 0x10, 0xd4, 0x06, 0x12, 0x0f, 0x0a, 0x0a, 0x4b, 0x61, 0x6e, 0x62, 0x61, 0x6e, 0x74, + 0x6f, 0x6f, 0x6c, 0x10, 0xd5, 0x06, 0x12, 0x10, 0x0a, 0x0b, 0x42, 0x72, 0x69, 0x67, 0x68, 0x74, + 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x10, 0xd6, 0x06, 0x12, 0x0c, 0x0a, 0x07, 0x48, 0x6f, 0x74, 0x77, + 0x69, 0x72, 0x65, 0x10, 0xd7, 0x06, 0x12, 0x0d, 0x0a, 0x08, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x62, + 0x6f, 0x74, 0x10, 0xd8, 0x06, 0x12, 0x0c, 0x0a, 0x07, 0x54, 0x69, 0x6d, 0x65, 0x6b, 0x69, 0x74, + 0x10, 0xd9, 0x06, 0x12, 0x10, 0x0a, 0x0b, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x73, 0x65, 0x6c, 0x6c, + 0x65, 0x72, 0x10, 0xda, 0x06, 0x12, 0x11, 0x0a, 0x0c, 0x4d, 0x6f, 0x6a, 0x6f, 0x68, 0x65, 0x6c, + 0x70, 0x64, 0x65, 0x73, 0x6b, 0x10, 0xdb, 0x06, 0x12, 0x0f, 0x0a, 0x0a, 0x43, 0x72, 0x65, 0x61, + 0x74, 0x65, 0x73, 0x65, 0x6e, 0x64, 0x10, 0xdc, 0x06, 0x12, 0x10, 0x0a, 0x0b, 0x47, 0x65, 0x74, + 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x10, 0xdd, 0x06, 0x12, 0x0c, 0x0a, 0x07, 0x44, + 0x79, 0x6e, 0x61, 0x64, 0x6f, 0x74, 0x10, 0xde, 0x06, 0x12, 0x0a, 0x0a, 0x05, 0x44, 0x65, 0x6d, + 0x69, 0x6f, 0x10, 0xdf, 0x06, 0x12, 0x0b, 0x0a, 0x06, 0x54, 0x6f, 0x6b, 0x65, 0x65, 0x74, 0x10, + 0xe0, 0x06, 0x12, 0x11, 0x0a, 0x0c, 0x4d, 0x79, 0x65, 0x78, 0x70, 0x65, 0x72, 0x69, 0x6d, 0x65, + 0x6e, 0x74, 0x10, 0xe1, 0x06, 0x12, 0x0e, 0x0a, 0x09, 0x43, 0x6f, 0x70, 0x79, 0x73, 0x63, 0x61, + 0x70, 0x65, 0x10, 0xe2, 0x06, 0x12, 0x0d, 0x0a, 0x08, 0x42, 0x65, 0x73, 0x6e, 0x61, 0x70, 0x70, + 0x79, 0x10, 0xe3, 0x06, 0x12, 0x0e, 0x0a, 0x09, 0x53, 0x61, 0x6c, 0x65, 0x73, 0x6d, 0x61, 0x74, + 0x65, 0x10, 0xe4, 0x06, 0x12, 0x0f, 0x0a, 0x0a, 0x48, 0x65, 0x61, 0x74, 0x6d, 0x61, 0x70, 0x61, + 0x70, 0x69, 0x10, 0xe5, 0x06, 0x12, 0x11, 0x0a, 0x0c, 0x57, 0x65, 0x62, 0x73, 0x69, 0x74, 0x65, + 0x70, 0x75, 0x6c, 0x73, 0x65, 0x10, 0xe6, 0x06, 0x12, 0x0e, 0x0a, 0x09, 0x55, 0x63, 0x6c, 0x61, + 0x73, 0x73, 0x69, 0x66, 0x79, 0x10, 0xe7, 0x06, 0x12, 0x0c, 0x0a, 0x07, 0x43, 0x6f, 0x6e, 0x76, + 0x65, 0x72, 0x74, 0x10, 0xe8, 0x06, 0x12, 0x0d, 0x0a, 0x08, 0x50, 0x44, 0x46, 0x6d, 0x79, 0x55, + 0x52, 0x4c, 0x10, 0xe9, 0x06, 0x12, 0x10, 0x0a, 0x0b, 0x41, 0x70, 0x69, 0x32, 0x43, 0x6f, 0x6e, + 0x76, 0x65, 0x72, 0x74, 0x10, 0xea, 0x06, 0x12, 0x0d, 0x0a, 0x08, 0x4f, 0x70, 0x73, 0x67, 0x65, + 0x6e, 0x69, 0x65, 0x10, 0xeb, 0x06, 0x12, 0x0b, 0x0a, 0x06, 0x47, 0x65, 0x6d, 0x69, 0x6e, 0x69, + 0x10, 0xec, 0x06, 0x12, 0x0e, 0x0a, 0x09, 0x48, 0x6f, 0x6e, 0x65, 0x79, 0x63, 0x6f, 0x6d, 0x62, + 0x10, 0xed, 0x06, 0x12, 0x14, 0x0a, 0x0f, 0x4b, 0x61, 0x6c, 0x74, 0x75, 0x72, 0x61, 0x41, 0x70, + 0x70, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x10, 0xee, 0x06, 0x12, 0x13, 0x0a, 0x0e, 0x4b, 0x61, 0x6c, + 0x74, 0x75, 0x72, 0x61, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x10, 0xef, 0x06, 0x12, 0x0a, + 0x0a, 0x05, 0x42, 0x69, 0x74, 0x47, 0x6f, 0x10, 0xf0, 0x06, 0x12, 0x0d, 0x0a, 0x08, 0x4f, 0x70, + 0x74, 0x69, 0x64, 0x61, 0x73, 0x68, 0x10, 0xf1, 0x06, 0x12, 0x0a, 0x0a, 0x05, 0x49, 0x6d, 0x67, + 0x69, 0x78, 0x10, 0xf2, 0x06, 0x12, 0x10, 0x0a, 0x0b, 0x49, 0x6d, 0x61, 0x67, 0x65, 0x54, 0x6f, + 0x54, 0x65, 0x78, 0x74, 0x10, 0xf3, 0x06, 0x12, 0x10, 0x0a, 0x0b, 0x50, 0x61, 0x67, 0x65, 0x32, + 0x49, 0x6d, 0x61, 0x67, 0x65, 0x73, 0x10, 0xf4, 0x06, 0x12, 0x0e, 0x0a, 0x09, 0x51, 0x75, 0x69, + 0x63, 0x6b, 0x62, 0x61, 0x73, 0x65, 0x10, 0xf5, 0x06, 0x12, 0x0d, 0x0a, 0x08, 0x52, 0x65, 0x64, + 0x62, 0x6f, 0x6f, 0x74, 0x68, 0x10, 0xf6, 0x06, 0x12, 0x0b, 0x0a, 0x06, 0x4e, 0x75, 0x62, 0x65, + 0x6c, 0x61, 0x10, 0xf7, 0x06, 0x12, 0x0c, 0x0a, 0x07, 0x49, 0x6e, 0x66, 0x6f, 0x62, 0x69, 0x70, + 0x10, 0xf8, 0x06, 0x12, 0x0a, 0x0a, 0x05, 0x55, 0x70, 0x72, 0x6f, 0x63, 0x10, 0xf9, 0x06, 0x12, + 0x0f, 0x0a, 0x0a, 0x53, 0x75, 0x70, 0x70, 0x6f, 0x72, 0x74, 0x62, 0x65, 0x65, 0x10, 0xfa, 0x06, + 0x12, 0x0e, 0x0a, 0x09, 0x41, 0x66, 0x74, 0x65, 0x72, 0x73, 0x68, 0x69, 0x70, 0x10, 0xfb, 0x06, + 0x12, 0x0c, 0x0a, 0x07, 0x45, 0x64, 0x75, 0x73, 0x69, 0x67, 0x6e, 0x10, 0xfc, 0x06, 0x12, 0x0b, + 0x0a, 0x06, 0x54, 0x65, 0x61, 0x6d, 0x75, 0x70, 0x10, 0xfd, 0x06, 0x12, 0x0c, 0x0a, 0x07, 0x57, + 0x6f, 0x72, 0x6b, 0x64, 0x61, 0x79, 0x10, 0xfe, 0x06, 0x12, 0x0c, 0x0a, 0x07, 0x4d, 0x6f, 0x6e, + 0x67, 0x6f, 0x44, 0x42, 0x10, 0xff, 0x06, 0x12, 0x08, 0x0a, 0x03, 0x4e, 0x47, 0x43, 0x10, 0x80, + 0x07, 0x12, 0x13, 0x0a, 0x0e, 0x44, 0x69, 0x67, 0x69, 0x74, 0x61, 0x6c, 0x4f, 0x63, 0x65, 0x61, + 0x6e, 0x56, 0x32, 0x10, 0x81, 0x07, 0x12, 0x0e, 0x0a, 0x09, 0x53, 0x51, 0x4c, 0x53, 0x65, 0x72, + 0x76, 0x65, 0x72, 0x10, 0x82, 0x07, 0x12, 0x08, 0x0a, 0x03, 0x46, 0x54, 0x50, 0x10, 0x83, 0x07, + 0x12, 0x0a, 0x0a, 0x05, 0x52, 0x65, 0x64, 0x69, 0x73, 0x10, 0x84, 0x07, 0x12, 0x09, 0x0a, 0x04, + 0x4c, 0x44, 0x41, 0x50, 0x10, 0x85, 0x07, 0x12, 0x0c, 0x0a, 0x07, 0x53, 0x68, 0x6f, 0x70, 0x69, + 0x66, 0x79, 0x10, 0x86, 0x07, 0x12, 0x0d, 0x0a, 0x08, 0x52, 0x61, 0x62, 0x62, 0x69, 0x74, 0x4d, + 0x51, 0x10, 0x87, 0x07, 0x12, 0x10, 0x0a, 0x0b, 0x43, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x52, 0x65, + 0x67, 0x65, 0x78, 0x10, 0x88, 0x07, 0x12, 0x0e, 0x0a, 0x09, 0x45, 0x74, 0x68, 0x65, 0x72, 0x73, + 0x63, 0x61, 0x6e, 0x10, 0x89, 0x07, 0x12, 0x0b, 0x0a, 0x06, 0x49, 0x6e, 0x66, 0x75, 0x72, 0x61, + 0x10, 0x8a, 0x07, 0x12, 0x0c, 0x0a, 0x07, 0x41, 0x6c, 0x63, 0x68, 0x65, 0x6d, 0x79, 0x10, 0x8b, + 0x07, 0x12, 0x10, 0x0a, 0x0b, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x4e, 0x61, 0x74, 0x69, 0x76, 0x65, + 0x10, 0x8c, 0x07, 0x12, 0x0c, 0x0a, 0x07, 0x4d, 0x6f, 0x72, 0x61, 0x6c, 0x69, 0x73, 0x10, 0x8d, + 0x07, 0x12, 0x0c, 0x0a, 0x07, 0x42, 0x73, 0x63, 0x53, 0x63, 0x61, 0x6e, 0x10, 0x8e, 0x07, 0x12, + 0x12, 0x0a, 0x0d, 0x43, 0x6f, 0x69, 0x6e, 0x4d, 0x61, 0x72, 0x6b, 0x65, 0x74, 0x43, 0x61, 0x70, + 0x10, 0x8f, 0x07, 0x12, 0x0a, 0x0a, 0x05, 0x50, 0x65, 0x72, 0x63, 0x79, 0x10, 0x90, 0x07, 0x12, + 0x11, 0x0a, 0x0c, 0x54, 0x69, 0x6e, 0x65, 0x73, 0x57, 0x65, 0x62, 0x68, 0x6f, 0x6f, 0x6b, 0x10, + 0x91, 0x07, 0x12, 0x0b, 0x0a, 0x06, 0x50, 0x75, 0x6c, 0x75, 0x6d, 0x69, 0x10, 0x92, 0x07, 0x12, + 0x12, 0x0a, 0x0d, 0x53, 0x75, 0x70, 0x61, 0x62, 0x61, 0x73, 0x65, 0x54, 0x6f, 0x6b, 0x65, 0x6e, + 0x10, 0x93, 0x07, 0x12, 0x10, 0x0a, 0x0b, 0x4e, 0x75, 0x47, 0x65, 0x74, 0x41, 0x70, 0x69, 0x4b, + 0x65, 0x79, 0x10, 0x94, 0x07, 0x12, 0x0a, 0x0a, 0x05, 0x41, 0x69, 0x76, 0x65, 0x6e, 0x10, 0x95, + 0x07, 0x12, 0x0c, 0x0a, 0x07, 0x50, 0x72, 0x65, 0x66, 0x65, 0x63, 0x74, 0x10, 0x96, 0x07, 0x12, + 0x0d, 0x0a, 0x08, 0x44, 0x6f, 0x63, 0x75, 0x73, 0x69, 0x67, 0x6e, 0x10, 0x97, 0x07, 0x12, 0x0e, + 0x0a, 0x09, 0x43, 0x6f, 0x75, 0x63, 0x68, 0x62, 0x61, 0x73, 0x65, 0x10, 0x98, 0x07, 0x12, 0x0e, + 0x0a, 0x09, 0x44, 0x6f, 0x63, 0x6b, 0x65, 0x72, 0x68, 0x75, 0x62, 0x10, 0x99, 0x07, 0x12, 0x19, + 0x0a, 0x14, 0x54, 0x72, 0x75, 0x66, 0x66, 0x6c, 0x65, 0x68, 0x6f, 0x67, 0x45, 0x6e, 0x74, 0x65, + 0x72, 0x70, 0x72, 0x69, 0x73, 0x65, 0x10, 0x9a, 0x07, 0x12, 0x10, 0x0a, 0x0b, 0x45, 0x6e, 0x76, + 0x6f, 0x79, 0x41, 0x70, 0x69, 0x4b, 0x65, 0x79, 0x10, 0x9b, 0x07, 0x12, 0x11, 0x0a, 0x0c, 0x47, + 0x69, 0x74, 0x48, 0x75, 0x62, 0x4f, 0x61, 0x75, 0x74, 0x68, 0x32, 0x10, 0x9c, 0x07, 0x12, 0x0f, + 0x0a, 0x0a, 0x53, 0x61, 0x6c, 0x65, 0x73, 0x66, 0x6f, 0x72, 0x63, 0x65, 0x10, 0x9d, 0x07, 0x12, + 0x10, 0x0a, 0x0b, 0x48, 0x75, 0x67, 0x67, 0x69, 0x6e, 0x67, 0x46, 0x61, 0x63, 0x65, 0x10, 0x9e, + 0x07, 0x12, 0x0e, 0x0a, 0x09, 0x53, 0x6e, 0x6f, 0x77, 0x66, 0x6c, 0x61, 0x6b, 0x65, 0x10, 0x9f, + 0x07, 0x12, 0x10, 0x0a, 0x0b, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x67, 0x72, 0x61, 0x70, 0x68, + 0x10, 0xa0, 0x07, 0x12, 0x0e, 0x0a, 0x09, 0x54, 0x61, 0x69, 0x6c, 0x73, 0x63, 0x61, 0x6c, 0x65, + 0x10, 0xa1, 0x07, 0x12, 0x10, 0x0a, 0x0b, 0x57, 0x65, 0x62, 0x33, 0x53, 0x74, 0x6f, 0x72, 0x61, + 0x67, 0x65, 0x10, 0xa2, 0x07, 0x12, 0x11, 0x0a, 0x0c, 0x41, 0x7a, 0x75, 0x72, 0x65, 0x53, 0x74, + 0x6f, 0x72, 0x61, 0x67, 0x65, 0x10, 0xa3, 0x07, 0x12, 0x12, 0x0a, 0x0d, 0x50, 0x6c, 0x61, 0x6e, + 0x65, 0x74, 0x53, 0x63, 0x61, 0x6c, 0x65, 0x44, 0x62, 0x10, 0xa4, 0x07, 0x12, 0x0e, 0x0a, 0x09, + 0x41, 0x6e, 0x74, 0x68, 0x72, 0x6f, 0x70, 0x69, 0x63, 0x10, 0xa5, 0x07, 0x12, 0x09, 0x0a, 0x04, + 0x52, 0x61, 0x6d, 0x70, 0x10, 0xa6, 0x07, 0x12, 0x0c, 0x0a, 0x07, 0x4b, 0x6c, 0x61, 0x76, 0x69, + 0x79, 0x6f, 0x10, 0xa7, 0x07, 0x12, 0x14, 0x0a, 0x0f, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x67, + 0x72, 0x61, 0x70, 0x68, 0x43, 0x6f, 0x64, 0x79, 0x10, 0xa8, 0x07, 0x12, 0x0e, 0x0a, 0x09, 0x56, + 0x6f, 0x69, 0x63, 0x65, 0x66, 0x6c, 0x6f, 0x77, 0x10, 0xa9, 0x07, 0x12, 0x0c, 0x0a, 0x07, 0x50, + 0x72, 0x69, 0x76, 0x61, 0x63, 0x79, 0x10, 0xaa, 0x07, 0x12, 0x0b, 0x0a, 0x06, 0x49, 0x50, 0x49, + 0x6e, 0x66, 0x6f, 0x10, 0xab, 0x07, 0x12, 0x10, 0x0a, 0x0b, 0x49, 0x70, 0x32, 0x6c, 0x6f, 0x63, + 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x10, 0xac, 0x07, 0x12, 0x0e, 0x0a, 0x09, 0x49, 0x6e, 0x73, 0x74, + 0x61, 0x6d, 0x6f, 0x6a, 0x6f, 0x10, 0xad, 0x07, 0x12, 0x0e, 0x0a, 0x09, 0x50, 0x6f, 0x72, 0x74, + 0x61, 0x69, 0x6e, 0x65, 0x72, 0x10, 0xae, 0x07, 0x12, 0x13, 0x0a, 0x0e, 0x50, 0x6f, 0x72, 0x74, + 0x61, 0x69, 0x6e, 0x65, 0x72, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x10, 0xaf, 0x07, 0x12, 0x0b, 0x0a, + 0x06, 0x4c, 0x6f, 0x67, 0x67, 0x6c, 0x79, 0x10, 0xb0, 0x07, 0x12, 0x0c, 0x0a, 0x07, 0x4f, 0x70, + 0x65, 0x6e, 0x56, 0x70, 0x6e, 0x10, 0xb1, 0x07, 0x12, 0x1e, 0x0a, 0x19, 0x56, 0x61, 0x67, 0x72, + 0x61, 0x6e, 0x74, 0x43, 0x6c, 0x6f, 0x75, 0x64, 0x50, 0x65, 0x72, 0x73, 0x6f, 0x6e, 0x61, 0x6c, + 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x10, 0xb2, 0x07, 0x42, 0x3d, 0x5a, 0x3b, 0x67, 0x69, 0x74, 0x68, + 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x74, 0x72, 0x75, 0x66, 0x66, 0x6c, 0x65, 0x73, 0x65, + 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x2f, 0x74, 0x72, 0x75, 0x66, 0x66, 0x6c, 0x65, 0x68, 0x6f, + 0x67, 0x2f, 0x76, 0x33, 0x2f, 0x70, 0x6b, 0x67, 0x2f, 0x70, 0x62, 0x2f, 0x64, 0x65, 0x74, 0x65, + 0x63, 0x74, 0x6f, 0x72, 0x73, 0x70, 0x62, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( diff --git a/pkg/pb/sourcespb/sources.pb.go b/pkg/pb/sourcespb/sources.pb.go index 011e85902f58..d95605d786b0 100644 --- a/pkg/pb/sourcespb/sources.pb.go +++ b/pkg/pb/sourcespb/sources.pb.go @@ -215,11 +215,20 @@ type LocalSource struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - Type string `protobuf:"bytes,1,opt,name=type,proto3" json:"type,omitempty"` - Name string `protobuf:"bytes,2,opt,name=name,proto3" json:"name,omitempty"` + Type string `protobuf:"bytes,1,opt,name=type,proto3" json:"type,omitempty"` + Name string `protobuf:"bytes,2,opt,name=name,proto3" json:"name,omitempty"` + // DEPRECATED: scan_interval is deprecated and can be removed when we no longer depend on the name. + // Deprecating in favor of scan_period due to the fact that scan_interval is a duration + // which is a fixed-length span of time represented as a count of seconds and fractions of seconds + // at nanosecond resolution. Most of the time, we want to be able to specify a scan interval in + // human-readable format (e.g. 45s, 30m, 12h, etc.) which is not possible with a duration. + // https://protobuf.dev/reference/protobuf/google.protobuf/#duration + // + // Deprecated: Do not use. ScanInterval *durationpb.Duration `protobuf:"bytes,3,opt,name=scan_interval,json=scanInterval,proto3" json:"scan_interval,omitempty"` Verify bool `protobuf:"varint,4,opt,name=verify,proto3" json:"verify,omitempty"` Connection *anypb.Any `protobuf:"bytes,5,opt,name=connection,proto3" json:"connection,omitempty"` + ScanPeriod string `protobuf:"bytes,6,opt,name=scan_period,json=scanPeriod,proto3" json:"scan_period,omitempty"` } func (x *LocalSource) Reset() { @@ -268,6 +277,7 @@ func (x *LocalSource) GetName() string { return "" } +// Deprecated: Do not use. func (x *LocalSource) GetScanInterval() *durationpb.Duration { if x != nil { return x.ScanInterval @@ -289,6 +299,13 @@ func (x *LocalSource) GetConnection() *anypb.Any { return nil } +func (x *LocalSource) GetScanPeriod() string { + if x != nil { + return x.ScanPeriod + } + return "" +} + type AzureStorage struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -3218,502 +3235,504 @@ var file_sources_proto_rawDesc = []byte{ 0x2f, 0x64, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x1f, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, - 0x22, 0xc3, 0x01, 0x0a, 0x0b, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, + 0x22, 0xe8, 0x01, 0x0a, 0x0b, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x3e, 0x0a, 0x0d, 0x73, 0x63, 0x61, 0x6e, + 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x42, 0x0a, 0x0d, 0x73, 0x63, 0x61, 0x6e, 0x5f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, - 0x66, 0x2e, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0c, 0x73, 0x63, 0x61, 0x6e, - 0x49, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x12, 0x16, 0x0a, 0x06, 0x76, 0x65, 0x72, 0x69, - 0x66, 0x79, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x06, 0x76, 0x65, 0x72, 0x69, 0x66, 0x79, - 0x12, 0x34, 0x0a, 0x0a, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x05, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, - 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x41, 0x6e, 0x79, 0x52, 0x0a, 0x63, 0x6f, 0x6e, 0x6e, - 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0xae, 0x02, 0x0a, 0x0c, 0x41, 0x7a, 0x75, 0x72, 0x65, - 0x53, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x12, 0x2d, 0x0a, 0x11, 0x63, 0x6f, 0x6e, 0x6e, 0x65, - 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x09, 0x48, 0x00, 0x52, 0x10, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, - 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x12, 0x37, 0x0a, 0x0a, 0x62, 0x61, 0x73, 0x69, 0x63, 0x5f, - 0x61, 0x75, 0x74, 0x68, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x63, 0x72, 0x65, - 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x73, 0x2e, 0x42, 0x61, 0x73, 0x69, 0x63, 0x41, 0x75, - 0x74, 0x68, 0x48, 0x00, 0x52, 0x09, 0x62, 0x61, 0x73, 0x69, 0x63, 0x41, 0x75, 0x74, 0x68, 0x12, - 0x2f, 0x0a, 0x12, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x5f, 0x63, 0x65, 0x72, 0x74, 0x69, 0x66, - 0x69, 0x63, 0x61, 0x74, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x11, 0x63, - 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, - 0x12, 0x48, 0x0a, 0x0f, 0x75, 0x6e, 0x61, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, - 0x74, 0x65, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x63, 0x72, 0x65, 0x64, - 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x73, 0x2e, 0x55, 0x6e, 0x61, 0x75, 0x74, 0x68, 0x65, 0x6e, - 0x74, 0x69, 0x63, 0x61, 0x74, 0x65, 0x64, 0x48, 0x00, 0x52, 0x0f, 0x75, 0x6e, 0x61, 0x75, 0x74, - 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x65, 0x64, 0x12, 0x2d, 0x0a, 0x12, 0x73, 0x74, - 0x6f, 0x72, 0x61, 0x67, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x73, - 0x18, 0x05, 0x20, 0x03, 0x28, 0x09, 0x52, 0x11, 0x73, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x43, - 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x73, 0x42, 0x0c, 0x0a, 0x0a, 0x63, 0x72, 0x65, - 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x22, 0x84, 0x02, 0x0a, 0x09, 0x42, 0x69, 0x74, 0x62, - 0x75, 0x63, 0x6b, 0x65, 0x74, 0x12, 0x24, 0x0a, 0x08, 0x65, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, - 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x08, 0xfa, 0x42, 0x05, 0x72, 0x03, 0x90, 0x01, - 0x01, 0x52, 0x08, 0x65, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x12, 0x16, 0x0a, 0x05, 0x74, - 0x6f, 0x6b, 0x65, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x05, 0x74, 0x6f, - 0x6b, 0x65, 0x6e, 0x12, 0x2b, 0x0a, 0x05, 0x6f, 0x61, 0x75, 0x74, 0x68, 0x18, 0x03, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x63, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x73, - 0x2e, 0x4f, 0x61, 0x75, 0x74, 0x68, 0x32, 0x48, 0x00, 0x52, 0x05, 0x6f, 0x61, 0x75, 0x74, 0x68, - 0x12, 0x37, 0x0a, 0x0a, 0x62, 0x61, 0x73, 0x69, 0x63, 0x5f, 0x61, 0x75, 0x74, 0x68, 0x18, 0x04, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x63, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, - 0x6c, 0x73, 0x2e, 0x42, 0x61, 0x73, 0x69, 0x63, 0x41, 0x75, 0x74, 0x68, 0x48, 0x00, 0x52, 0x09, - 0x62, 0x61, 0x73, 0x69, 0x63, 0x41, 0x75, 0x74, 0x68, 0x12, 0x22, 0x0a, 0x0c, 0x72, 0x65, 0x70, - 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x69, 0x65, 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, 0x09, 0x52, - 0x0c, 0x72, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x69, 0x65, 0x73, 0x12, 0x21, 0x0a, - 0x0c, 0x69, 0x67, 0x6e, 0x6f, 0x72, 0x65, 0x5f, 0x72, 0x65, 0x70, 0x6f, 0x73, 0x18, 0x06, 0x20, - 0x03, 0x28, 0x09, 0x52, 0x0b, 0x69, 0x67, 0x6e, 0x6f, 0x72, 0x65, 0x52, 0x65, 0x70, 0x6f, 0x73, - 0x42, 0x0c, 0x0a, 0x0a, 0x63, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x22, 0x56, - 0x0a, 0x08, 0x43, 0x69, 0x72, 0x63, 0x6c, 0x65, 0x43, 0x49, 0x12, 0x24, 0x0a, 0x08, 0x65, 0x6e, + 0x66, 0x2e, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x42, 0x02, 0x18, 0x01, 0x52, 0x0c, + 0x73, 0x63, 0x61, 0x6e, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x12, 0x16, 0x0a, 0x06, + 0x76, 0x65, 0x72, 0x69, 0x66, 0x79, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x06, 0x76, 0x65, + 0x72, 0x69, 0x66, 0x79, 0x12, 0x34, 0x0a, 0x0a, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, + 0x6f, 0x6e, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, + 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x41, 0x6e, 0x79, 0x52, 0x0a, + 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x1f, 0x0a, 0x0b, 0x73, 0x63, + 0x61, 0x6e, 0x5f, 0x70, 0x65, 0x72, 0x69, 0x6f, 0x64, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x0a, 0x73, 0x63, 0x61, 0x6e, 0x50, 0x65, 0x72, 0x69, 0x6f, 0x64, 0x22, 0xae, 0x02, 0x0a, 0x0c, + 0x41, 0x7a, 0x75, 0x72, 0x65, 0x53, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x12, 0x2d, 0x0a, 0x11, + 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x73, 0x74, 0x72, 0x69, 0x6e, + 0x67, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x10, 0x63, 0x6f, 0x6e, 0x6e, 0x65, + 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x12, 0x37, 0x0a, 0x0a, 0x62, + 0x61, 0x73, 0x69, 0x63, 0x5f, 0x61, 0x75, 0x74, 0x68, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x16, 0x2e, 0x63, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x73, 0x2e, 0x42, 0x61, + 0x73, 0x69, 0x63, 0x41, 0x75, 0x74, 0x68, 0x48, 0x00, 0x52, 0x09, 0x62, 0x61, 0x73, 0x69, 0x63, + 0x41, 0x75, 0x74, 0x68, 0x12, 0x2f, 0x0a, 0x12, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x5f, 0x63, + 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, + 0x48, 0x00, 0x52, 0x11, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, + 0x69, 0x63, 0x61, 0x74, 0x65, 0x12, 0x48, 0x0a, 0x0f, 0x75, 0x6e, 0x61, 0x75, 0x74, 0x68, 0x65, + 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x65, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, + 0x2e, 0x63, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x73, 0x2e, 0x55, 0x6e, 0x61, + 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x65, 0x64, 0x48, 0x00, 0x52, 0x0f, + 0x75, 0x6e, 0x61, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x65, 0x64, 0x12, + 0x2d, 0x0a, 0x12, 0x73, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x61, + 0x69, 0x6e, 0x65, 0x72, 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, 0x09, 0x52, 0x11, 0x73, 0x74, 0x6f, + 0x72, 0x61, 0x67, 0x65, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x73, 0x42, 0x0c, + 0x0a, 0x0a, 0x63, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x22, 0x84, 0x02, 0x0a, + 0x09, 0x42, 0x69, 0x74, 0x62, 0x75, 0x63, 0x6b, 0x65, 0x74, 0x12, 0x24, 0x0a, 0x08, 0x65, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x08, 0xfa, 0x42, 0x05, 0x72, 0x03, 0x90, 0x01, 0x01, 0x52, 0x08, 0x65, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x12, 0x16, 0x0a, 0x05, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x48, - 0x00, 0x52, 0x05, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x42, 0x0c, 0x0a, 0x0a, 0x63, 0x72, 0x65, 0x64, - 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x22, 0xa7, 0x04, 0x0a, 0x0a, 0x43, 0x6f, 0x6e, 0x66, 0x6c, - 0x75, 0x65, 0x6e, 0x63, 0x65, 0x12, 0x24, 0x0a, 0x08, 0x65, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, - 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x08, 0xfa, 0x42, 0x05, 0x72, 0x03, 0x90, 0x01, - 0x01, 0x52, 0x08, 0x65, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x12, 0x48, 0x0a, 0x0f, 0x75, - 0x6e, 0x61, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x65, 0x64, 0x18, 0x02, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x63, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, - 0x6c, 0x73, 0x2e, 0x55, 0x6e, 0x61, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, - 0x65, 0x64, 0x48, 0x00, 0x52, 0x0f, 0x75, 0x6e, 0x61, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, - 0x63, 0x61, 0x74, 0x65, 0x64, 0x12, 0x37, 0x0a, 0x0a, 0x62, 0x61, 0x73, 0x69, 0x63, 0x5f, 0x61, - 0x75, 0x74, 0x68, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x63, 0x72, 0x65, 0x64, + 0x00, 0x52, 0x05, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x12, 0x2b, 0x0a, 0x05, 0x6f, 0x61, 0x75, 0x74, + 0x68, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x63, 0x72, 0x65, 0x64, 0x65, 0x6e, + 0x74, 0x69, 0x61, 0x6c, 0x73, 0x2e, 0x4f, 0x61, 0x75, 0x74, 0x68, 0x32, 0x48, 0x00, 0x52, 0x05, + 0x6f, 0x61, 0x75, 0x74, 0x68, 0x12, 0x37, 0x0a, 0x0a, 0x62, 0x61, 0x73, 0x69, 0x63, 0x5f, 0x61, + 0x75, 0x74, 0x68, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x63, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x73, 0x2e, 0x42, 0x61, 0x73, 0x69, 0x63, 0x41, 0x75, 0x74, - 0x68, 0x48, 0x00, 0x52, 0x09, 0x62, 0x61, 0x73, 0x69, 0x63, 0x41, 0x75, 0x74, 0x68, 0x12, 0x16, - 0x0a, 0x05, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, - 0x05, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x12, 0x48, 0x0a, 0x0c, 0x73, 0x70, 0x61, 0x63, 0x65, 0x73, - 0x5f, 0x73, 0x63, 0x6f, 0x70, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x25, 0x2e, 0x73, - 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x2e, 0x43, 0x6f, 0x6e, 0x66, 0x6c, 0x75, 0x65, 0x6e, 0x63, - 0x65, 0x2e, 0x47, 0x65, 0x74, 0x41, 0x6c, 0x6c, 0x53, 0x70, 0x61, 0x63, 0x65, 0x73, 0x53, 0x63, - 0x6f, 0x70, 0x65, 0x52, 0x0b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x73, 0x53, 0x63, 0x6f, 0x70, 0x65, - 0x12, 0x37, 0x0a, 0x18, 0x69, 0x6e, 0x73, 0x65, 0x63, 0x75, 0x72, 0x65, 0x5f, 0x73, 0x6b, 0x69, - 0x70, 0x5f, 0x76, 0x65, 0x72, 0x69, 0x66, 0x79, 0x5f, 0x74, 0x6c, 0x73, 0x18, 0x06, 0x20, 0x01, - 0x28, 0x08, 0x52, 0x15, 0x69, 0x6e, 0x73, 0x65, 0x63, 0x75, 0x72, 0x65, 0x53, 0x6b, 0x69, 0x70, - 0x56, 0x65, 0x72, 0x69, 0x66, 0x79, 0x54, 0x6c, 0x73, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x70, 0x61, - 0x63, 0x65, 0x73, 0x18, 0x07, 0x20, 0x03, 0x28, 0x09, 0x52, 0x06, 0x73, 0x70, 0x61, 0x63, 0x65, - 0x73, 0x12, 0x23, 0x0a, 0x0d, 0x69, 0x67, 0x6e, 0x6f, 0x72, 0x65, 0x5f, 0x73, 0x70, 0x61, 0x63, - 0x65, 0x73, 0x18, 0x08, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0c, 0x69, 0x67, 0x6e, 0x6f, 0x72, 0x65, - 0x53, 0x70, 0x61, 0x63, 0x65, 0x73, 0x12, 0x2f, 0x0a, 0x13, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, - 0x65, 0x5f, 0x61, 0x74, 0x74, 0x61, 0x63, 0x68, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x18, 0x09, 0x20, - 0x01, 0x28, 0x08, 0x52, 0x12, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x41, 0x74, 0x74, 0x61, - 0x63, 0x68, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x12, 0x21, 0x0a, 0x0c, 0x73, 0x6b, 0x69, 0x70, 0x5f, - 0x68, 0x69, 0x73, 0x74, 0x6f, 0x72, 0x79, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0b, 0x73, - 0x6b, 0x69, 0x70, 0x48, 0x69, 0x73, 0x74, 0x6f, 0x72, 0x79, 0x22, 0x36, 0x0a, 0x11, 0x47, 0x65, - 0x74, 0x41, 0x6c, 0x6c, 0x53, 0x70, 0x61, 0x63, 0x65, 0x73, 0x53, 0x63, 0x6f, 0x70, 0x65, 0x12, - 0x07, 0x0a, 0x03, 0x41, 0x4c, 0x4c, 0x10, 0x00, 0x12, 0x0a, 0x0a, 0x06, 0x47, 0x4c, 0x4f, 0x42, - 0x41, 0x4c, 0x10, 0x01, 0x12, 0x0c, 0x0a, 0x08, 0x50, 0x45, 0x52, 0x53, 0x4f, 0x4e, 0x41, 0x4c, - 0x10, 0x02, 0x42, 0x0c, 0x0a, 0x0a, 0x63, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, - 0x22, 0x81, 0x02, 0x0a, 0x06, 0x44, 0x6f, 0x63, 0x6b, 0x65, 0x72, 0x12, 0x48, 0x0a, 0x0f, 0x75, - 0x6e, 0x61, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x65, 0x64, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x63, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, - 0x6c, 0x73, 0x2e, 0x55, 0x6e, 0x61, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, - 0x65, 0x64, 0x48, 0x00, 0x52, 0x0f, 0x75, 0x6e, 0x61, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, - 0x63, 0x61, 0x74, 0x65, 0x64, 0x12, 0x37, 0x0a, 0x0a, 0x62, 0x61, 0x73, 0x69, 0x63, 0x5f, 0x61, - 0x75, 0x74, 0x68, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x63, 0x72, 0x65, 0x64, - 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x73, 0x2e, 0x42, 0x61, 0x73, 0x69, 0x63, 0x41, 0x75, 0x74, - 0x68, 0x48, 0x00, 0x52, 0x09, 0x62, 0x61, 0x73, 0x69, 0x63, 0x41, 0x75, 0x74, 0x68, 0x12, 0x23, - 0x0a, 0x0c, 0x62, 0x65, 0x61, 0x72, 0x65, 0x72, 0x5f, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x18, 0x03, - 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x0b, 0x62, 0x65, 0x61, 0x72, 0x65, 0x72, 0x54, 0x6f, - 0x6b, 0x65, 0x6e, 0x12, 0x29, 0x0a, 0x0f, 0x64, 0x6f, 0x63, 0x6b, 0x65, 0x72, 0x5f, 0x6b, 0x65, - 0x79, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x48, 0x00, 0x52, 0x0e, - 0x64, 0x6f, 0x63, 0x6b, 0x65, 0x72, 0x4b, 0x65, 0x79, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x12, 0x16, - 0x0a, 0x06, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, 0x09, 0x52, 0x06, - 0x69, 0x6d, 0x61, 0x67, 0x65, 0x73, 0x42, 0x0c, 0x0a, 0x0a, 0x63, 0x72, 0x65, 0x64, 0x65, 0x6e, - 0x74, 0x69, 0x61, 0x6c, 0x22, 0x6c, 0x0a, 0x03, 0x45, 0x43, 0x52, 0x12, 0x37, 0x0a, 0x0a, 0x61, - 0x63, 0x63, 0x65, 0x73, 0x73, 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x16, 0x2e, 0x63, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x73, 0x2e, 0x4b, 0x65, - 0x79, 0x53, 0x65, 0x63, 0x72, 0x65, 0x74, 0x48, 0x00, 0x52, 0x09, 0x61, 0x63, 0x63, 0x65, 0x73, - 0x73, 0x4b, 0x65, 0x79, 0x12, 0x1e, 0x0a, 0x0a, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x69, - 0x65, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0a, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, - 0x72, 0x69, 0x65, 0x73, 0x42, 0x0c, 0x0a, 0x0a, 0x63, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, - 0x61, 0x6c, 0x22, 0x44, 0x0a, 0x0a, 0x46, 0x69, 0x6c, 0x65, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, - 0x12, 0x20, 0x0a, 0x0b, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x69, 0x65, 0x73, 0x18, - 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0b, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x69, - 0x65, 0x73, 0x12, 0x14, 0x0a, 0x05, 0x70, 0x61, 0x74, 0x68, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, - 0x09, 0x52, 0x05, 0x70, 0x61, 0x74, 0x68, 0x73, 0x22, 0xab, 0x04, 0x0a, 0x03, 0x47, 0x43, 0x53, - 0x12, 0x32, 0x0a, 0x14, 0x6a, 0x73, 0x6f, 0x6e, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, - 0x5f, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, - 0x52, 0x12, 0x6a, 0x73, 0x6f, 0x6e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x41, 0x63, 0x63, - 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x19, 0x0a, 0x07, 0x61, 0x70, 0x69, 0x5f, 0x6b, 0x65, 0x79, 0x18, - 0x02, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x06, 0x61, 0x70, 0x69, 0x4b, 0x65, 0x79, 0x12, - 0x48, 0x0a, 0x0f, 0x75, 0x6e, 0x61, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, - 0x65, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x63, 0x72, 0x65, 0x64, 0x65, - 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x73, 0x2e, 0x55, 0x6e, 0x61, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, - 0x69, 0x63, 0x61, 0x74, 0x65, 0x64, 0x48, 0x00, 0x52, 0x0f, 0x75, 0x6e, 0x61, 0x75, 0x74, 0x68, - 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x65, 0x64, 0x12, 0x31, 0x0a, 0x03, 0x61, 0x64, 0x63, - 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x63, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, - 0x69, 0x61, 0x6c, 0x73, 0x2e, 0x43, 0x6c, 0x6f, 0x75, 0x64, 0x45, 0x6e, 0x76, 0x69, 0x72, 0x6f, - 0x6e, 0x6d, 0x65, 0x6e, 0x74, 0x48, 0x00, 0x52, 0x03, 0x61, 0x64, 0x63, 0x12, 0x32, 0x0a, 0x14, - 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x5f, - 0x66, 0x69, 0x6c, 0x65, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x12, 0x73, 0x65, - 0x72, 0x76, 0x69, 0x63, 0x65, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x46, 0x69, 0x6c, 0x65, - 0x12, 0x2b, 0x0a, 0x05, 0x6f, 0x61, 0x75, 0x74, 0x68, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x13, 0x2e, 0x63, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x73, 0x2e, 0x4f, 0x61, - 0x75, 0x74, 0x68, 0x32, 0x48, 0x00, 0x52, 0x05, 0x6f, 0x61, 0x75, 0x74, 0x68, 0x12, 0x1d, 0x0a, - 0x0a, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x05, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x09, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x49, 0x64, 0x12, 0x27, 0x0a, 0x0f, - 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x5f, 0x62, 0x75, 0x63, 0x6b, 0x65, 0x74, 0x73, 0x18, - 0x06, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0e, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x42, 0x75, - 0x63, 0x6b, 0x65, 0x74, 0x73, 0x12, 0x27, 0x0a, 0x0f, 0x65, 0x78, 0x63, 0x6c, 0x75, 0x64, 0x65, - 0x5f, 0x62, 0x75, 0x63, 0x6b, 0x65, 0x74, 0x73, 0x18, 0x07, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0e, - 0x65, 0x78, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x42, 0x75, 0x63, 0x6b, 0x65, 0x74, 0x73, 0x12, 0x27, - 0x0a, 0x0f, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x5f, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, - 0x73, 0x18, 0x08, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0e, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, - 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x12, 0x27, 0x0a, 0x0f, 0x65, 0x78, 0x63, 0x6c, 0x75, - 0x64, 0x65, 0x5f, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x18, 0x09, 0x20, 0x03, 0x28, 0x09, - 0x52, 0x0e, 0x65, 0x78, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x73, - 0x12, 0x26, 0x0a, 0x0f, 0x6d, 0x61, 0x78, 0x5f, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x5f, 0x73, - 0x69, 0x7a, 0x65, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0d, 0x6d, 0x61, 0x78, 0x4f, 0x62, - 0x6a, 0x65, 0x63, 0x74, 0x53, 0x69, 0x7a, 0x65, 0x42, 0x0c, 0x0a, 0x0a, 0x63, 0x72, 0x65, 0x64, - 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x22, 0x8f, 0x02, 0x0a, 0x03, 0x47, 0x69, 0x74, 0x12, 0x37, - 0x0a, 0x0a, 0x62, 0x61, 0x73, 0x69, 0x63, 0x5f, 0x61, 0x75, 0x74, 0x68, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x63, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x73, - 0x2e, 0x42, 0x61, 0x73, 0x69, 0x63, 0x41, 0x75, 0x74, 0x68, 0x48, 0x00, 0x52, 0x09, 0x62, 0x61, - 0x73, 0x69, 0x63, 0x41, 0x75, 0x74, 0x68, 0x12, 0x48, 0x0a, 0x0f, 0x75, 0x6e, 0x61, 0x75, 0x74, - 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x65, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x1c, 0x2e, 0x63, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x73, 0x2e, 0x55, - 0x6e, 0x61, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x65, 0x64, 0x48, 0x00, - 0x52, 0x0f, 0x75, 0x6e, 0x61, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x65, - 0x64, 0x12, 0x31, 0x0a, 0x08, 0x73, 0x73, 0x68, 0x5f, 0x61, 0x75, 0x74, 0x68, 0x18, 0x05, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x63, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, - 0x73, 0x2e, 0x53, 0x53, 0x48, 0x41, 0x75, 0x74, 0x68, 0x48, 0x00, 0x52, 0x07, 0x73, 0x73, 0x68, - 0x41, 0x75, 0x74, 0x68, 0x12, 0x20, 0x0a, 0x0b, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x6f, 0x72, - 0x69, 0x65, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0b, 0x64, 0x69, 0x72, 0x65, 0x63, - 0x74, 0x6f, 0x72, 0x69, 0x65, 0x73, 0x12, 0x22, 0x0a, 0x0c, 0x72, 0x65, 0x70, 0x6f, 0x73, 0x69, - 0x74, 0x6f, 0x72, 0x69, 0x65, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0c, 0x72, 0x65, - 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x69, 0x65, 0x73, 0x42, 0x0c, 0x0a, 0x0a, 0x63, 0x72, - 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x22, 0x81, 0x02, 0x0a, 0x06, 0x47, 0x69, 0x74, - 0x4c, 0x61, 0x62, 0x12, 0x24, 0x0a, 0x08, 0x65, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x08, 0xfa, 0x42, 0x05, 0x72, 0x03, 0x90, 0x01, 0x01, 0x52, - 0x08, 0x65, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x12, 0x16, 0x0a, 0x05, 0x74, 0x6f, 0x6b, - 0x65, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x05, 0x74, 0x6f, 0x6b, 0x65, - 0x6e, 0x12, 0x2b, 0x0a, 0x05, 0x6f, 0x61, 0x75, 0x74, 0x68, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x13, 0x2e, 0x63, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x73, 0x2e, 0x4f, - 0x61, 0x75, 0x74, 0x68, 0x32, 0x48, 0x00, 0x52, 0x05, 0x6f, 0x61, 0x75, 0x74, 0x68, 0x12, 0x37, - 0x0a, 0x0a, 0x62, 0x61, 0x73, 0x69, 0x63, 0x5f, 0x61, 0x75, 0x74, 0x68, 0x18, 0x04, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x63, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x73, - 0x2e, 0x42, 0x61, 0x73, 0x69, 0x63, 0x41, 0x75, 0x74, 0x68, 0x48, 0x00, 0x52, 0x09, 0x62, 0x61, - 0x73, 0x69, 0x63, 0x41, 0x75, 0x74, 0x68, 0x12, 0x22, 0x0a, 0x0c, 0x72, 0x65, 0x70, 0x6f, 0x73, - 0x69, 0x74, 0x6f, 0x72, 0x69, 0x65, 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0c, 0x72, - 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x69, 0x65, 0x73, 0x12, 0x21, 0x0a, 0x0c, 0x69, - 0x67, 0x6e, 0x6f, 0x72, 0x65, 0x5f, 0x72, 0x65, 0x70, 0x6f, 0x73, 0x18, 0x06, 0x20, 0x03, 0x28, - 0x09, 0x52, 0x0b, 0x69, 0x67, 0x6e, 0x6f, 0x72, 0x65, 0x52, 0x65, 0x70, 0x6f, 0x73, 0x42, 0x0c, - 0x0a, 0x0a, 0x63, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x22, 0xb0, 0x05, 0x0a, - 0x06, 0x47, 0x69, 0x74, 0x48, 0x75, 0x62, 0x12, 0x24, 0x0a, 0x08, 0x65, 0x6e, 0x64, 0x70, 0x6f, - 0x69, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x08, 0xfa, 0x42, 0x05, 0x72, 0x03, - 0x90, 0x01, 0x01, 0x52, 0x08, 0x65, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x12, 0x37, 0x0a, - 0x0a, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x5f, 0x61, 0x70, 0x70, 0x18, 0x02, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x16, 0x2e, 0x63, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x73, 0x2e, - 0x47, 0x69, 0x74, 0x48, 0x75, 0x62, 0x41, 0x70, 0x70, 0x48, 0x00, 0x52, 0x09, 0x67, 0x69, 0x74, - 0x68, 0x75, 0x62, 0x41, 0x70, 0x70, 0x12, 0x16, 0x0a, 0x05, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x18, - 0x03, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x05, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x12, 0x48, - 0x0a, 0x0f, 0x75, 0x6e, 0x61, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x65, - 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x63, 0x72, 0x65, 0x64, 0x65, 0x6e, - 0x74, 0x69, 0x61, 0x6c, 0x73, 0x2e, 0x55, 0x6e, 0x61, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, - 0x63, 0x61, 0x74, 0x65, 0x64, 0x48, 0x00, 0x52, 0x0f, 0x75, 0x6e, 0x61, 0x75, 0x74, 0x68, 0x65, - 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x65, 0x64, 0x12, 0x37, 0x0a, 0x0a, 0x62, 0x61, 0x73, 0x69, - 0x63, 0x5f, 0x61, 0x75, 0x74, 0x68, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x63, - 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x73, 0x2e, 0x42, 0x61, 0x73, 0x69, 0x63, - 0x41, 0x75, 0x74, 0x68, 0x48, 0x00, 0x52, 0x09, 0x62, 0x61, 0x73, 0x69, 0x63, 0x41, 0x75, 0x74, - 0x68, 0x12, 0x22, 0x0a, 0x0c, 0x72, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x69, 0x65, - 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0c, 0x72, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, - 0x6f, 0x72, 0x69, 0x65, 0x73, 0x12, 0x24, 0x0a, 0x0d, 0x6f, 0x72, 0x67, 0x61, 0x6e, 0x69, 0x7a, - 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x06, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0d, 0x6f, 0x72, - 0x67, 0x61, 0x6e, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x1c, 0x0a, 0x09, 0x73, - 0x63, 0x61, 0x6e, 0x55, 0x73, 0x65, 0x72, 0x73, 0x18, 0x07, 0x20, 0x01, 0x28, 0x08, 0x52, 0x09, - 0x73, 0x63, 0x61, 0x6e, 0x55, 0x73, 0x65, 0x72, 0x73, 0x12, 0x22, 0x0a, 0x0c, 0x69, 0x6e, 0x63, - 0x6c, 0x75, 0x64, 0x65, 0x46, 0x6f, 0x72, 0x6b, 0x73, 0x18, 0x08, 0x20, 0x01, 0x28, 0x08, 0x52, - 0x0c, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x46, 0x6f, 0x72, 0x6b, 0x73, 0x12, 0x12, 0x0a, - 0x04, 0x68, 0x65, 0x61, 0x64, 0x18, 0x09, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x68, 0x65, 0x61, - 0x64, 0x12, 0x12, 0x0a, 0x04, 0x62, 0x61, 0x73, 0x65, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x04, 0x62, 0x61, 0x73, 0x65, 0x12, 0x20, 0x0a, 0x0b, 0x69, 0x67, 0x6e, 0x6f, 0x72, 0x65, 0x52, - 0x65, 0x70, 0x6f, 0x73, 0x18, 0x0b, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0b, 0x69, 0x67, 0x6e, 0x6f, - 0x72, 0x65, 0x52, 0x65, 0x70, 0x6f, 0x73, 0x12, 0x22, 0x0a, 0x0c, 0x69, 0x6e, 0x63, 0x6c, 0x75, - 0x64, 0x65, 0x52, 0x65, 0x70, 0x6f, 0x73, 0x18, 0x0c, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0c, 0x69, - 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x52, 0x65, 0x70, 0x6f, 0x73, 0x12, 0x3e, 0x0a, 0x1a, 0x69, - 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x50, 0x75, 0x6c, 0x6c, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x43, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x08, 0x52, - 0x1a, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x50, 0x75, 0x6c, 0x6c, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x43, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x12, 0x32, 0x0a, 0x14, 0x69, - 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x49, 0x73, 0x73, 0x75, 0x65, 0x43, 0x6f, 0x6d, 0x6d, 0x65, - 0x6e, 0x74, 0x73, 0x18, 0x0f, 0x20, 0x01, 0x28, 0x08, 0x52, 0x14, 0x69, 0x6e, 0x63, 0x6c, 0x75, - 0x64, 0x65, 0x49, 0x73, 0x73, 0x75, 0x65, 0x43, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x12, - 0x30, 0x0a, 0x13, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x47, 0x69, 0x73, 0x74, 0x43, 0x6f, - 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x18, 0x10, 0x20, 0x01, 0x28, 0x08, 0x52, 0x13, 0x69, 0x6e, - 0x63, 0x6c, 0x75, 0x64, 0x65, 0x47, 0x69, 0x73, 0x74, 0x43, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, - 0x73, 0x42, 0x0c, 0x0a, 0x0a, 0x63, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x22, - 0x42, 0x0a, 0x0b, 0x47, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x44, 0x72, 0x69, 0x76, 0x65, 0x12, 0x25, - 0x0a, 0x0d, 0x72, 0x65, 0x66, 0x72, 0x65, 0x73, 0x68, 0x5f, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x0c, 0x72, 0x65, 0x66, 0x72, 0x65, 0x73, 0x68, - 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x42, 0x0c, 0x0a, 0x0a, 0x63, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, - 0x69, 0x61, 0x6c, 0x22, 0x80, 0x03, 0x0a, 0x04, 0x4a, 0x49, 0x52, 0x41, 0x12, 0x24, 0x0a, 0x08, + 0x68, 0x48, 0x00, 0x52, 0x09, 0x62, 0x61, 0x73, 0x69, 0x63, 0x41, 0x75, 0x74, 0x68, 0x12, 0x22, + 0x0a, 0x0c, 0x72, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x69, 0x65, 0x73, 0x18, 0x05, + 0x20, 0x03, 0x28, 0x09, 0x52, 0x0c, 0x72, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x69, + 0x65, 0x73, 0x12, 0x21, 0x0a, 0x0c, 0x69, 0x67, 0x6e, 0x6f, 0x72, 0x65, 0x5f, 0x72, 0x65, 0x70, + 0x6f, 0x73, 0x18, 0x06, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0b, 0x69, 0x67, 0x6e, 0x6f, 0x72, 0x65, + 0x52, 0x65, 0x70, 0x6f, 0x73, 0x42, 0x0c, 0x0a, 0x0a, 0x63, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, + 0x69, 0x61, 0x6c, 0x22, 0x56, 0x0a, 0x08, 0x43, 0x69, 0x72, 0x63, 0x6c, 0x65, 0x43, 0x49, 0x12, + 0x24, 0x0a, 0x08, 0x65, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x09, 0x42, 0x08, 0xfa, 0x42, 0x05, 0x72, 0x03, 0x90, 0x01, 0x01, 0x52, 0x08, 0x65, 0x6e, 0x64, + 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x12, 0x16, 0x0a, 0x05, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x05, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x42, 0x0c, 0x0a, + 0x0a, 0x63, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x22, 0xa7, 0x04, 0x0a, 0x0a, + 0x43, 0x6f, 0x6e, 0x66, 0x6c, 0x75, 0x65, 0x6e, 0x63, 0x65, 0x12, 0x24, 0x0a, 0x08, 0x65, 0x6e, + 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x08, 0xfa, 0x42, + 0x05, 0x72, 0x03, 0x90, 0x01, 0x01, 0x52, 0x08, 0x65, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, + 0x12, 0x48, 0x0a, 0x0f, 0x75, 0x6e, 0x61, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, + 0x74, 0x65, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x63, 0x72, 0x65, 0x64, + 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x73, 0x2e, 0x55, 0x6e, 0x61, 0x75, 0x74, 0x68, 0x65, 0x6e, + 0x74, 0x69, 0x63, 0x61, 0x74, 0x65, 0x64, 0x48, 0x00, 0x52, 0x0f, 0x75, 0x6e, 0x61, 0x75, 0x74, + 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x65, 0x64, 0x12, 0x37, 0x0a, 0x0a, 0x62, 0x61, + 0x73, 0x69, 0x63, 0x5f, 0x61, 0x75, 0x74, 0x68, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, + 0x2e, 0x63, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x73, 0x2e, 0x42, 0x61, 0x73, + 0x69, 0x63, 0x41, 0x75, 0x74, 0x68, 0x48, 0x00, 0x52, 0x09, 0x62, 0x61, 0x73, 0x69, 0x63, 0x41, + 0x75, 0x74, 0x68, 0x12, 0x16, 0x0a, 0x05, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x18, 0x04, 0x20, 0x01, + 0x28, 0x09, 0x48, 0x00, 0x52, 0x05, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x12, 0x48, 0x0a, 0x0c, 0x73, + 0x70, 0x61, 0x63, 0x65, 0x73, 0x5f, 0x73, 0x63, 0x6f, 0x70, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, + 0x0e, 0x32, 0x25, 0x2e, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x2e, 0x43, 0x6f, 0x6e, 0x66, + 0x6c, 0x75, 0x65, 0x6e, 0x63, 0x65, 0x2e, 0x47, 0x65, 0x74, 0x41, 0x6c, 0x6c, 0x53, 0x70, 0x61, + 0x63, 0x65, 0x73, 0x53, 0x63, 0x6f, 0x70, 0x65, 0x52, 0x0b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x73, + 0x53, 0x63, 0x6f, 0x70, 0x65, 0x12, 0x37, 0x0a, 0x18, 0x69, 0x6e, 0x73, 0x65, 0x63, 0x75, 0x72, + 0x65, 0x5f, 0x73, 0x6b, 0x69, 0x70, 0x5f, 0x76, 0x65, 0x72, 0x69, 0x66, 0x79, 0x5f, 0x74, 0x6c, + 0x73, 0x18, 0x06, 0x20, 0x01, 0x28, 0x08, 0x52, 0x15, 0x69, 0x6e, 0x73, 0x65, 0x63, 0x75, 0x72, + 0x65, 0x53, 0x6b, 0x69, 0x70, 0x56, 0x65, 0x72, 0x69, 0x66, 0x79, 0x54, 0x6c, 0x73, 0x12, 0x16, + 0x0a, 0x06, 0x73, 0x70, 0x61, 0x63, 0x65, 0x73, 0x18, 0x07, 0x20, 0x03, 0x28, 0x09, 0x52, 0x06, + 0x73, 0x70, 0x61, 0x63, 0x65, 0x73, 0x12, 0x23, 0x0a, 0x0d, 0x69, 0x67, 0x6e, 0x6f, 0x72, 0x65, + 0x5f, 0x73, 0x70, 0x61, 0x63, 0x65, 0x73, 0x18, 0x08, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0c, 0x69, + 0x67, 0x6e, 0x6f, 0x72, 0x65, 0x53, 0x70, 0x61, 0x63, 0x65, 0x73, 0x12, 0x2f, 0x0a, 0x13, 0x69, + 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x5f, 0x61, 0x74, 0x74, 0x61, 0x63, 0x68, 0x6d, 0x65, 0x6e, + 0x74, 0x73, 0x18, 0x09, 0x20, 0x01, 0x28, 0x08, 0x52, 0x12, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, + 0x65, 0x41, 0x74, 0x74, 0x61, 0x63, 0x68, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x12, 0x21, 0x0a, 0x0c, + 0x73, 0x6b, 0x69, 0x70, 0x5f, 0x68, 0x69, 0x73, 0x74, 0x6f, 0x72, 0x79, 0x18, 0x0a, 0x20, 0x01, + 0x28, 0x08, 0x52, 0x0b, 0x73, 0x6b, 0x69, 0x70, 0x48, 0x69, 0x73, 0x74, 0x6f, 0x72, 0x79, 0x22, + 0x36, 0x0a, 0x11, 0x47, 0x65, 0x74, 0x41, 0x6c, 0x6c, 0x53, 0x70, 0x61, 0x63, 0x65, 0x73, 0x53, + 0x63, 0x6f, 0x70, 0x65, 0x12, 0x07, 0x0a, 0x03, 0x41, 0x4c, 0x4c, 0x10, 0x00, 0x12, 0x0a, 0x0a, + 0x06, 0x47, 0x4c, 0x4f, 0x42, 0x41, 0x4c, 0x10, 0x01, 0x12, 0x0c, 0x0a, 0x08, 0x50, 0x45, 0x52, + 0x53, 0x4f, 0x4e, 0x41, 0x4c, 0x10, 0x02, 0x42, 0x0c, 0x0a, 0x0a, 0x63, 0x72, 0x65, 0x64, 0x65, + 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x22, 0x81, 0x02, 0x0a, 0x06, 0x44, 0x6f, 0x63, 0x6b, 0x65, 0x72, + 0x12, 0x48, 0x0a, 0x0f, 0x75, 0x6e, 0x61, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, + 0x74, 0x65, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x63, 0x72, 0x65, 0x64, + 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x73, 0x2e, 0x55, 0x6e, 0x61, 0x75, 0x74, 0x68, 0x65, 0x6e, + 0x74, 0x69, 0x63, 0x61, 0x74, 0x65, 0x64, 0x48, 0x00, 0x52, 0x0f, 0x75, 0x6e, 0x61, 0x75, 0x74, + 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x65, 0x64, 0x12, 0x37, 0x0a, 0x0a, 0x62, 0x61, + 0x73, 0x69, 0x63, 0x5f, 0x61, 0x75, 0x74, 0x68, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, + 0x2e, 0x63, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x73, 0x2e, 0x42, 0x61, 0x73, + 0x69, 0x63, 0x41, 0x75, 0x74, 0x68, 0x48, 0x00, 0x52, 0x09, 0x62, 0x61, 0x73, 0x69, 0x63, 0x41, + 0x75, 0x74, 0x68, 0x12, 0x23, 0x0a, 0x0c, 0x62, 0x65, 0x61, 0x72, 0x65, 0x72, 0x5f, 0x74, 0x6f, + 0x6b, 0x65, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x0b, 0x62, 0x65, 0x61, + 0x72, 0x65, 0x72, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x12, 0x29, 0x0a, 0x0f, 0x64, 0x6f, 0x63, 0x6b, + 0x65, 0x72, 0x5f, 0x6b, 0x65, 0x79, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, + 0x08, 0x48, 0x00, 0x52, 0x0e, 0x64, 0x6f, 0x63, 0x6b, 0x65, 0x72, 0x4b, 0x65, 0x79, 0x63, 0x68, + 0x61, 0x69, 0x6e, 0x12, 0x16, 0x0a, 0x06, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x73, 0x18, 0x05, 0x20, + 0x03, 0x28, 0x09, 0x52, 0x06, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x73, 0x42, 0x0c, 0x0a, 0x0a, 0x63, + 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x22, 0x6c, 0x0a, 0x03, 0x45, 0x43, 0x52, + 0x12, 0x37, 0x0a, 0x0a, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x63, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, + 0x6c, 0x73, 0x2e, 0x4b, 0x65, 0x79, 0x53, 0x65, 0x63, 0x72, 0x65, 0x74, 0x48, 0x00, 0x52, 0x09, + 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x4b, 0x65, 0x79, 0x12, 0x1e, 0x0a, 0x0a, 0x72, 0x65, 0x67, + 0x69, 0x73, 0x74, 0x72, 0x69, 0x65, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0a, 0x72, + 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x69, 0x65, 0x73, 0x42, 0x0c, 0x0a, 0x0a, 0x63, 0x72, 0x65, + 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x22, 0x44, 0x0a, 0x0a, 0x46, 0x69, 0x6c, 0x65, 0x73, + 0x79, 0x73, 0x74, 0x65, 0x6d, 0x12, 0x20, 0x0a, 0x0b, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x6f, + 0x72, 0x69, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0b, 0x64, 0x69, 0x72, 0x65, + 0x63, 0x74, 0x6f, 0x72, 0x69, 0x65, 0x73, 0x12, 0x14, 0x0a, 0x05, 0x70, 0x61, 0x74, 0x68, 0x73, + 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, 0x05, 0x70, 0x61, 0x74, 0x68, 0x73, 0x22, 0xab, 0x04, + 0x0a, 0x03, 0x47, 0x43, 0x53, 0x12, 0x32, 0x0a, 0x14, 0x6a, 0x73, 0x6f, 0x6e, 0x5f, 0x73, 0x65, + 0x72, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x12, 0x6a, 0x73, 0x6f, 0x6e, 0x53, 0x65, 0x72, 0x76, 0x69, + 0x63, 0x65, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x19, 0x0a, 0x07, 0x61, 0x70, 0x69, + 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x06, 0x61, 0x70, + 0x69, 0x4b, 0x65, 0x79, 0x12, 0x48, 0x0a, 0x0f, 0x75, 0x6e, 0x61, 0x75, 0x74, 0x68, 0x65, 0x6e, + 0x74, 0x69, 0x63, 0x61, 0x74, 0x65, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, + 0x63, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x73, 0x2e, 0x55, 0x6e, 0x61, 0x75, + 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x65, 0x64, 0x48, 0x00, 0x52, 0x0f, 0x75, + 0x6e, 0x61, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x65, 0x64, 0x12, 0x31, + 0x0a, 0x03, 0x61, 0x64, 0x63, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x63, 0x72, + 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x73, 0x2e, 0x43, 0x6c, 0x6f, 0x75, 0x64, 0x45, + 0x6e, 0x76, 0x69, 0x72, 0x6f, 0x6e, 0x6d, 0x65, 0x6e, 0x74, 0x48, 0x00, 0x52, 0x03, 0x61, 0x64, + 0x63, 0x12, 0x32, 0x0a, 0x14, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x61, 0x63, 0x63, + 0x6f, 0x75, 0x6e, 0x74, 0x5f, 0x66, 0x69, 0x6c, 0x65, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x09, 0x48, + 0x00, 0x52, 0x12, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, + 0x74, 0x46, 0x69, 0x6c, 0x65, 0x12, 0x2b, 0x0a, 0x05, 0x6f, 0x61, 0x75, 0x74, 0x68, 0x18, 0x0c, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x63, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, + 0x6c, 0x73, 0x2e, 0x4f, 0x61, 0x75, 0x74, 0x68, 0x32, 0x48, 0x00, 0x52, 0x05, 0x6f, 0x61, 0x75, + 0x74, 0x68, 0x12, 0x1d, 0x0a, 0x0a, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x5f, 0x69, 0x64, + 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x49, + 0x64, 0x12, 0x27, 0x0a, 0x0f, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x5f, 0x62, 0x75, 0x63, + 0x6b, 0x65, 0x74, 0x73, 0x18, 0x06, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0e, 0x69, 0x6e, 0x63, 0x6c, + 0x75, 0x64, 0x65, 0x42, 0x75, 0x63, 0x6b, 0x65, 0x74, 0x73, 0x12, 0x27, 0x0a, 0x0f, 0x65, 0x78, + 0x63, 0x6c, 0x75, 0x64, 0x65, 0x5f, 0x62, 0x75, 0x63, 0x6b, 0x65, 0x74, 0x73, 0x18, 0x07, 0x20, + 0x03, 0x28, 0x09, 0x52, 0x0e, 0x65, 0x78, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x42, 0x75, 0x63, 0x6b, + 0x65, 0x74, 0x73, 0x12, 0x27, 0x0a, 0x0f, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x5f, 0x6f, + 0x62, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x18, 0x08, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0e, 0x69, 0x6e, + 0x63, 0x6c, 0x75, 0x64, 0x65, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x12, 0x27, 0x0a, 0x0f, + 0x65, 0x78, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x5f, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x18, + 0x09, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0e, 0x65, 0x78, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x4f, 0x62, + 0x6a, 0x65, 0x63, 0x74, 0x73, 0x12, 0x26, 0x0a, 0x0f, 0x6d, 0x61, 0x78, 0x5f, 0x6f, 0x62, 0x6a, + 0x65, 0x63, 0x74, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0d, + 0x6d, 0x61, 0x78, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x53, 0x69, 0x7a, 0x65, 0x42, 0x0c, 0x0a, + 0x0a, 0x63, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x22, 0x8f, 0x02, 0x0a, 0x03, + 0x47, 0x69, 0x74, 0x12, 0x37, 0x0a, 0x0a, 0x62, 0x61, 0x73, 0x69, 0x63, 0x5f, 0x61, 0x75, 0x74, + 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x63, 0x72, 0x65, 0x64, 0x65, 0x6e, + 0x74, 0x69, 0x61, 0x6c, 0x73, 0x2e, 0x42, 0x61, 0x73, 0x69, 0x63, 0x41, 0x75, 0x74, 0x68, 0x48, + 0x00, 0x52, 0x09, 0x62, 0x61, 0x73, 0x69, 0x63, 0x41, 0x75, 0x74, 0x68, 0x12, 0x48, 0x0a, 0x0f, + 0x75, 0x6e, 0x61, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x65, 0x64, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x63, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, + 0x61, 0x6c, 0x73, 0x2e, 0x55, 0x6e, 0x61, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, + 0x74, 0x65, 0x64, 0x48, 0x00, 0x52, 0x0f, 0x75, 0x6e, 0x61, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, + 0x69, 0x63, 0x61, 0x74, 0x65, 0x64, 0x12, 0x31, 0x0a, 0x08, 0x73, 0x73, 0x68, 0x5f, 0x61, 0x75, + 0x74, 0x68, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x63, 0x72, 0x65, 0x64, 0x65, + 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x73, 0x2e, 0x53, 0x53, 0x48, 0x41, 0x75, 0x74, 0x68, 0x48, 0x00, + 0x52, 0x07, 0x73, 0x73, 0x68, 0x41, 0x75, 0x74, 0x68, 0x12, 0x20, 0x0a, 0x0b, 0x64, 0x69, 0x72, + 0x65, 0x63, 0x74, 0x6f, 0x72, 0x69, 0x65, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0b, + 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x69, 0x65, 0x73, 0x12, 0x22, 0x0a, 0x0c, 0x72, + 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x69, 0x65, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, + 0x09, 0x52, 0x0c, 0x72, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x69, 0x65, 0x73, 0x42, + 0x0c, 0x0a, 0x0a, 0x63, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x22, 0x81, 0x02, + 0x0a, 0x06, 0x47, 0x69, 0x74, 0x4c, 0x61, 0x62, 0x12, 0x24, 0x0a, 0x08, 0x65, 0x6e, 0x64, 0x70, + 0x6f, 0x69, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x08, 0xfa, 0x42, 0x05, 0x72, + 0x03, 0x90, 0x01, 0x01, 0x52, 0x08, 0x65, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x12, 0x16, + 0x0a, 0x05, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, + 0x05, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x12, 0x2b, 0x0a, 0x05, 0x6f, 0x61, 0x75, 0x74, 0x68, 0x18, + 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x63, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, + 0x61, 0x6c, 0x73, 0x2e, 0x4f, 0x61, 0x75, 0x74, 0x68, 0x32, 0x48, 0x00, 0x52, 0x05, 0x6f, 0x61, + 0x75, 0x74, 0x68, 0x12, 0x37, 0x0a, 0x0a, 0x62, 0x61, 0x73, 0x69, 0x63, 0x5f, 0x61, 0x75, 0x74, + 0x68, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x63, 0x72, 0x65, 0x64, 0x65, 0x6e, + 0x74, 0x69, 0x61, 0x6c, 0x73, 0x2e, 0x42, 0x61, 0x73, 0x69, 0x63, 0x41, 0x75, 0x74, 0x68, 0x48, + 0x00, 0x52, 0x09, 0x62, 0x61, 0x73, 0x69, 0x63, 0x41, 0x75, 0x74, 0x68, 0x12, 0x22, 0x0a, 0x0c, + 0x72, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x69, 0x65, 0x73, 0x18, 0x05, 0x20, 0x03, + 0x28, 0x09, 0x52, 0x0c, 0x72, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x69, 0x65, 0x73, + 0x12, 0x21, 0x0a, 0x0c, 0x69, 0x67, 0x6e, 0x6f, 0x72, 0x65, 0x5f, 0x72, 0x65, 0x70, 0x6f, 0x73, + 0x18, 0x06, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0b, 0x69, 0x67, 0x6e, 0x6f, 0x72, 0x65, 0x52, 0x65, + 0x70, 0x6f, 0x73, 0x42, 0x0c, 0x0a, 0x0a, 0x63, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, + 0x6c, 0x22, 0xb0, 0x05, 0x0a, 0x06, 0x47, 0x69, 0x74, 0x48, 0x75, 0x62, 0x12, 0x24, 0x0a, 0x08, 0x65, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x08, 0xfa, 0x42, 0x05, 0x72, 0x03, 0x90, 0x01, 0x01, 0x52, 0x08, 0x65, 0x6e, 0x64, 0x70, 0x6f, 0x69, - 0x6e, 0x74, 0x12, 0x37, 0x0a, 0x0a, 0x62, 0x61, 0x73, 0x69, 0x63, 0x5f, 0x61, 0x75, 0x74, 0x68, + 0x6e, 0x74, 0x12, 0x37, 0x0a, 0x0a, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x5f, 0x61, 0x70, 0x70, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x63, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, - 0x69, 0x61, 0x6c, 0x73, 0x2e, 0x42, 0x61, 0x73, 0x69, 0x63, 0x41, 0x75, 0x74, 0x68, 0x48, 0x00, - 0x52, 0x09, 0x62, 0x61, 0x73, 0x69, 0x63, 0x41, 0x75, 0x74, 0x68, 0x12, 0x48, 0x0a, 0x0f, 0x75, - 0x6e, 0x61, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x65, 0x64, 0x18, 0x03, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x63, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, - 0x6c, 0x73, 0x2e, 0x55, 0x6e, 0x61, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, - 0x65, 0x64, 0x48, 0x00, 0x52, 0x0f, 0x75, 0x6e, 0x61, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, - 0x63, 0x61, 0x74, 0x65, 0x64, 0x12, 0x2b, 0x0a, 0x05, 0x6f, 0x61, 0x75, 0x74, 0x68, 0x18, 0x04, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x63, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, - 0x6c, 0x73, 0x2e, 0x4f, 0x61, 0x75, 0x74, 0x68, 0x32, 0x48, 0x00, 0x52, 0x05, 0x6f, 0x61, 0x75, - 0x74, 0x68, 0x12, 0x16, 0x0a, 0x05, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x18, 0x06, 0x20, 0x01, 0x28, - 0x09, 0x48, 0x00, 0x52, 0x05, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x12, 0x1a, 0x0a, 0x08, 0x70, 0x72, - 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, 0x09, 0x52, 0x08, 0x70, 0x72, - 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x12, 0x27, 0x0a, 0x0f, 0x69, 0x67, 0x6e, 0x6f, 0x72, 0x65, - 0x5f, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x18, 0x07, 0x20, 0x03, 0x28, 0x09, 0x52, - 0x0e, 0x69, 0x67, 0x6e, 0x6f, 0x72, 0x65, 0x50, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x12, - 0x37, 0x0a, 0x18, 0x69, 0x6e, 0x73, 0x65, 0x63, 0x75, 0x72, 0x65, 0x5f, 0x73, 0x6b, 0x69, 0x70, - 0x5f, 0x76, 0x65, 0x72, 0x69, 0x66, 0x79, 0x5f, 0x74, 0x6c, 0x73, 0x18, 0x08, 0x20, 0x01, 0x28, - 0x08, 0x52, 0x15, 0x69, 0x6e, 0x73, 0x65, 0x63, 0x75, 0x72, 0x65, 0x53, 0x6b, 0x69, 0x70, 0x56, - 0x65, 0x72, 0x69, 0x66, 0x79, 0x54, 0x6c, 0x73, 0x42, 0x0c, 0x0a, 0x0a, 0x63, 0x72, 0x65, 0x64, - 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x22, 0x73, 0x0a, 0x19, 0x4e, 0x50, 0x4d, 0x55, 0x6e, 0x61, - 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x65, 0x64, 0x50, 0x61, 0x63, 0x6b, - 0x61, 0x67, 0x65, 0x12, 0x48, 0x0a, 0x0f, 0x75, 0x6e, 0x61, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, - 0x69, 0x63, 0x61, 0x74, 0x65, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x63, + 0x69, 0x61, 0x6c, 0x73, 0x2e, 0x47, 0x69, 0x74, 0x48, 0x75, 0x62, 0x41, 0x70, 0x70, 0x48, 0x00, + 0x52, 0x09, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x41, 0x70, 0x70, 0x12, 0x16, 0x0a, 0x05, 0x74, + 0x6f, 0x6b, 0x65, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x05, 0x74, 0x6f, + 0x6b, 0x65, 0x6e, 0x12, 0x48, 0x0a, 0x0f, 0x75, 0x6e, 0x61, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, + 0x69, 0x63, 0x61, 0x74, 0x65, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x63, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x73, 0x2e, 0x55, 0x6e, 0x61, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x65, 0x64, 0x48, 0x00, 0x52, 0x0f, 0x75, 0x6e, - 0x61, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x65, 0x64, 0x42, 0x0c, 0x0a, - 0x0a, 0x63, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x22, 0x74, 0x0a, 0x1a, 0x50, - 0x79, 0x50, 0x49, 0x55, 0x6e, 0x61, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, - 0x65, 0x64, 0x50, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x12, 0x48, 0x0a, 0x0f, 0x75, 0x6e, 0x61, - 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x65, 0x64, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x63, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x73, - 0x2e, 0x55, 0x6e, 0x61, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x65, 0x64, - 0x48, 0x00, 0x52, 0x0f, 0x75, 0x6e, 0x61, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, - 0x74, 0x65, 0x64, 0x42, 0x0c, 0x0a, 0x0a, 0x63, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, - 0x6c, 0x22, 0x86, 0x03, 0x0a, 0x02, 0x53, 0x33, 0x12, 0x37, 0x0a, 0x0a, 0x61, 0x63, 0x63, 0x65, - 0x73, 0x73, 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x63, - 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x73, 0x2e, 0x4b, 0x65, 0x79, 0x53, 0x65, - 0x63, 0x72, 0x65, 0x74, 0x48, 0x00, 0x52, 0x09, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x4b, 0x65, - 0x79, 0x12, 0x48, 0x0a, 0x0f, 0x75, 0x6e, 0x61, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, - 0x61, 0x74, 0x65, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x63, 0x72, 0x65, - 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x73, 0x2e, 0x55, 0x6e, 0x61, 0x75, 0x74, 0x68, 0x65, - 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x65, 0x64, 0x48, 0x00, 0x52, 0x0f, 0x75, 0x6e, 0x61, 0x75, - 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x65, 0x64, 0x12, 0x4c, 0x0a, 0x11, 0x63, - 0x6c, 0x6f, 0x75, 0x64, 0x5f, 0x65, 0x6e, 0x76, 0x69, 0x72, 0x6f, 0x6e, 0x6d, 0x65, 0x6e, 0x74, - 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x63, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, - 0x69, 0x61, 0x6c, 0x73, 0x2e, 0x43, 0x6c, 0x6f, 0x75, 0x64, 0x45, 0x6e, 0x76, 0x69, 0x72, 0x6f, - 0x6e, 0x6d, 0x65, 0x6e, 0x74, 0x48, 0x00, 0x52, 0x10, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x45, 0x6e, - 0x76, 0x69, 0x72, 0x6f, 0x6e, 0x6d, 0x65, 0x6e, 0x74, 0x12, 0x49, 0x0a, 0x0d, 0x73, 0x65, 0x73, - 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x22, 0x2e, 0x63, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x73, 0x2e, 0x41, - 0x57, 0x53, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x53, 0x65, - 0x63, 0x72, 0x65, 0x74, 0x48, 0x00, 0x52, 0x0c, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x54, - 0x6f, 0x6b, 0x65, 0x6e, 0x12, 0x18, 0x0a, 0x07, 0x62, 0x75, 0x63, 0x6b, 0x65, 0x74, 0x73, 0x18, - 0x03, 0x20, 0x03, 0x28, 0x09, 0x52, 0x07, 0x62, 0x75, 0x63, 0x6b, 0x65, 0x74, 0x73, 0x12, 0x26, - 0x0a, 0x0f, 0x6d, 0x61, 0x78, 0x5f, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x5f, 0x73, 0x69, 0x7a, - 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0d, 0x6d, 0x61, 0x78, 0x4f, 0x62, 0x6a, 0x65, - 0x63, 0x74, 0x53, 0x69, 0x7a, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x72, 0x6f, 0x6c, 0x65, 0x73, 0x18, - 0x07, 0x20, 0x03, 0x28, 0x09, 0x52, 0x05, 0x72, 0x6f, 0x6c, 0x65, 0x73, 0x42, 0x0c, 0x0a, 0x0a, - 0x63, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x22, 0xc3, 0x01, 0x0a, 0x05, 0x53, - 0x6c, 0x61, 0x63, 0x6b, 0x12, 0x24, 0x0a, 0x08, 0x65, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x08, 0xfa, 0x42, 0x05, 0x72, 0x03, 0x90, 0x01, 0x01, - 0x52, 0x08, 0x65, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x12, 0x16, 0x0a, 0x05, 0x74, 0x6f, - 0x6b, 0x65, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x05, 0x74, 0x6f, 0x6b, - 0x65, 0x6e, 0x12, 0x32, 0x0a, 0x06, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x73, 0x18, 0x05, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x63, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x73, - 0x2e, 0x53, 0x6c, 0x61, 0x63, 0x6b, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x73, 0x48, 0x00, 0x52, 0x06, - 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x73, 0x12, 0x1a, 0x0a, 0x08, 0x63, 0x68, 0x61, 0x6e, 0x6e, 0x65, - 0x6c, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x09, 0x52, 0x08, 0x63, 0x68, 0x61, 0x6e, 0x6e, 0x65, - 0x6c, 0x73, 0x12, 0x1e, 0x0a, 0x0a, 0x69, 0x67, 0x6e, 0x6f, 0x72, 0x65, 0x4c, 0x69, 0x73, 0x74, - 0x18, 0x04, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0a, 0x69, 0x67, 0x6e, 0x6f, 0x72, 0x65, 0x4c, 0x69, - 0x73, 0x74, 0x42, 0x0c, 0x0a, 0x0a, 0x63, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, - 0x22, 0x06, 0x0a, 0x04, 0x54, 0x65, 0x73, 0x74, 0x22, 0x31, 0x0a, 0x09, 0x42, 0x75, 0x69, 0x6c, - 0x64, 0x6b, 0x69, 0x74, 0x65, 0x12, 0x16, 0x0a, 0x05, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x05, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x42, 0x0c, 0x0a, - 0x0a, 0x63, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x22, 0xdb, 0x01, 0x0a, 0x06, - 0x47, 0x65, 0x72, 0x72, 0x69, 0x74, 0x12, 0x24, 0x0a, 0x08, 0x65, 0x6e, 0x64, 0x70, 0x6f, 0x69, - 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x08, 0xfa, 0x42, 0x05, 0x72, 0x03, 0x90, - 0x01, 0x01, 0x52, 0x08, 0x65, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x12, 0x37, 0x0a, 0x0a, - 0x62, 0x61, 0x73, 0x69, 0x63, 0x5f, 0x61, 0x75, 0x74, 0x68, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x16, 0x2e, 0x63, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x73, 0x2e, 0x42, - 0x61, 0x73, 0x69, 0x63, 0x41, 0x75, 0x74, 0x68, 0x48, 0x00, 0x52, 0x09, 0x62, 0x61, 0x73, 0x69, - 0x63, 0x41, 0x75, 0x74, 0x68, 0x12, 0x48, 0x0a, 0x0f, 0x75, 0x6e, 0x61, 0x75, 0x74, 0x68, 0x65, - 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x65, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, - 0x2e, 0x63, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x73, 0x2e, 0x55, 0x6e, 0x61, - 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x65, 0x64, 0x48, 0x00, 0x52, 0x0f, - 0x75, 0x6e, 0x61, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x65, 0x64, 0x12, - 0x1a, 0x0a, 0x08, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, - 0x09, 0x52, 0x08, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x42, 0x0c, 0x0a, 0x0a, 0x63, - 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x22, 0xde, 0x01, 0x0a, 0x07, 0x4a, 0x65, - 0x6e, 0x6b, 0x69, 0x6e, 0x73, 0x12, 0x24, 0x0a, 0x08, 0x65, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, - 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x08, 0xfa, 0x42, 0x05, 0x72, 0x03, 0x90, 0x01, - 0x01, 0x52, 0x08, 0x65, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x12, 0x37, 0x0a, 0x0a, 0x62, - 0x61, 0x73, 0x69, 0x63, 0x5f, 0x61, 0x75, 0x74, 0x68, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x16, 0x2e, 0x63, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x73, 0x2e, 0x42, 0x61, - 0x73, 0x69, 0x63, 0x41, 0x75, 0x74, 0x68, 0x48, 0x00, 0x52, 0x09, 0x62, 0x61, 0x73, 0x69, 0x63, - 0x41, 0x75, 0x74, 0x68, 0x12, 0x2d, 0x0a, 0x06, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x18, 0x03, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x63, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, - 0x6c, 0x73, 0x2e, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x48, 0x00, 0x52, 0x06, 0x68, 0x65, 0x61, - 0x64, 0x65, 0x72, 0x12, 0x37, 0x0a, 0x18, 0x69, 0x6e, 0x73, 0x65, 0x63, 0x75, 0x72, 0x65, 0x5f, - 0x73, 0x6b, 0x69, 0x70, 0x5f, 0x76, 0x65, 0x72, 0x69, 0x66, 0x79, 0x5f, 0x74, 0x6c, 0x73, 0x18, - 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x15, 0x69, 0x6e, 0x73, 0x65, 0x63, 0x75, 0x72, 0x65, 0x53, - 0x6b, 0x69, 0x70, 0x56, 0x65, 0x72, 0x69, 0x66, 0x79, 0x54, 0x6c, 0x73, 0x42, 0x0c, 0x0a, 0x0a, - 0x63, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x22, 0x9f, 0x02, 0x0a, 0x05, 0x54, - 0x65, 0x61, 0x6d, 0x73, 0x12, 0x24, 0x0a, 0x08, 0x65, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x08, 0xfa, 0x42, 0x05, 0x72, 0x03, 0x90, 0x01, 0x01, - 0x52, 0x08, 0x65, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x12, 0x16, 0x0a, 0x05, 0x74, 0x6f, - 0x6b, 0x65, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x05, 0x74, 0x6f, 0x6b, - 0x65, 0x6e, 0x12, 0x46, 0x0a, 0x0d, 0x61, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, - 0x74, 0x65, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x63, 0x72, 0x65, 0x64, - 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x73, 0x2e, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x43, 0x72, - 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x73, 0x48, 0x00, 0x52, 0x0d, 0x61, 0x75, 0x74, + 0x61, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x65, 0x64, 0x12, 0x37, 0x0a, + 0x0a, 0x62, 0x61, 0x73, 0x69, 0x63, 0x5f, 0x61, 0x75, 0x74, 0x68, 0x18, 0x0d, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x16, 0x2e, 0x63, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x73, 0x2e, + 0x42, 0x61, 0x73, 0x69, 0x63, 0x41, 0x75, 0x74, 0x68, 0x48, 0x00, 0x52, 0x09, 0x62, 0x61, 0x73, + 0x69, 0x63, 0x41, 0x75, 0x74, 0x68, 0x12, 0x22, 0x0a, 0x0c, 0x72, 0x65, 0x70, 0x6f, 0x73, 0x69, + 0x74, 0x6f, 0x72, 0x69, 0x65, 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0c, 0x72, 0x65, + 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x69, 0x65, 0x73, 0x12, 0x24, 0x0a, 0x0d, 0x6f, 0x72, + 0x67, 0x61, 0x6e, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x06, 0x20, 0x03, 0x28, + 0x09, 0x52, 0x0d, 0x6f, 0x72, 0x67, 0x61, 0x6e, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, + 0x12, 0x1c, 0x0a, 0x09, 0x73, 0x63, 0x61, 0x6e, 0x55, 0x73, 0x65, 0x72, 0x73, 0x18, 0x07, 0x20, + 0x01, 0x28, 0x08, 0x52, 0x09, 0x73, 0x63, 0x61, 0x6e, 0x55, 0x73, 0x65, 0x72, 0x73, 0x12, 0x22, + 0x0a, 0x0c, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x46, 0x6f, 0x72, 0x6b, 0x73, 0x18, 0x08, + 0x20, 0x01, 0x28, 0x08, 0x52, 0x0c, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x46, 0x6f, 0x72, + 0x6b, 0x73, 0x12, 0x12, 0x0a, 0x04, 0x68, 0x65, 0x61, 0x64, 0x18, 0x09, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x04, 0x68, 0x65, 0x61, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x62, 0x61, 0x73, 0x65, 0x18, 0x0a, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x62, 0x61, 0x73, 0x65, 0x12, 0x20, 0x0a, 0x0b, 0x69, 0x67, + 0x6e, 0x6f, 0x72, 0x65, 0x52, 0x65, 0x70, 0x6f, 0x73, 0x18, 0x0b, 0x20, 0x03, 0x28, 0x09, 0x52, + 0x0b, 0x69, 0x67, 0x6e, 0x6f, 0x72, 0x65, 0x52, 0x65, 0x70, 0x6f, 0x73, 0x12, 0x22, 0x0a, 0x0c, + 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x52, 0x65, 0x70, 0x6f, 0x73, 0x18, 0x0c, 0x20, 0x03, + 0x28, 0x09, 0x52, 0x0c, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x52, 0x65, 0x70, 0x6f, 0x73, + 0x12, 0x3e, 0x0a, 0x1a, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x50, 0x75, 0x6c, 0x6c, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x43, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x18, 0x0e, + 0x20, 0x01, 0x28, 0x08, 0x52, 0x1a, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x50, 0x75, 0x6c, + 0x6c, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x43, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x73, + 0x12, 0x32, 0x0a, 0x14, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x49, 0x73, 0x73, 0x75, 0x65, + 0x43, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x18, 0x0f, 0x20, 0x01, 0x28, 0x08, 0x52, 0x14, + 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x49, 0x73, 0x73, 0x75, 0x65, 0x43, 0x6f, 0x6d, 0x6d, + 0x65, 0x6e, 0x74, 0x73, 0x12, 0x30, 0x0a, 0x13, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x47, + 0x69, 0x73, 0x74, 0x43, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x18, 0x10, 0x20, 0x01, 0x28, + 0x08, 0x52, 0x13, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x47, 0x69, 0x73, 0x74, 0x43, 0x6f, + 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x42, 0x0c, 0x0a, 0x0a, 0x63, 0x72, 0x65, 0x64, 0x65, 0x6e, + 0x74, 0x69, 0x61, 0x6c, 0x22, 0x42, 0x0a, 0x0b, 0x47, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x44, 0x72, + 0x69, 0x76, 0x65, 0x12, 0x25, 0x0a, 0x0d, 0x72, 0x65, 0x66, 0x72, 0x65, 0x73, 0x68, 0x5f, 0x74, + 0x6f, 0x6b, 0x65, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x0c, 0x72, 0x65, + 0x66, 0x72, 0x65, 0x73, 0x68, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x42, 0x0c, 0x0a, 0x0a, 0x63, 0x72, + 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x22, 0x80, 0x03, 0x0a, 0x04, 0x4a, 0x49, 0x52, + 0x41, 0x12, 0x24, 0x0a, 0x08, 0x65, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x09, 0x42, 0x08, 0xfa, 0x42, 0x05, 0x72, 0x03, 0x90, 0x01, 0x01, 0x52, 0x08, 0x65, + 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x12, 0x37, 0x0a, 0x0a, 0x62, 0x61, 0x73, 0x69, 0x63, + 0x5f, 0x61, 0x75, 0x74, 0x68, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x63, 0x72, + 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x73, 0x2e, 0x42, 0x61, 0x73, 0x69, 0x63, 0x41, + 0x75, 0x74, 0x68, 0x48, 0x00, 0x52, 0x09, 0x62, 0x61, 0x73, 0x69, 0x63, 0x41, 0x75, 0x74, 0x68, + 0x12, 0x48, 0x0a, 0x0f, 0x75, 0x6e, 0x61, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, + 0x74, 0x65, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x63, 0x72, 0x65, 0x64, + 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x73, 0x2e, 0x55, 0x6e, 0x61, 0x75, 0x74, 0x68, 0x65, 0x6e, + 0x74, 0x69, 0x63, 0x61, 0x74, 0x65, 0x64, 0x48, 0x00, 0x52, 0x0f, 0x75, 0x6e, 0x61, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x65, 0x64, 0x12, 0x2b, 0x0a, 0x05, 0x6f, 0x61, - 0x75, 0x74, 0x68, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x63, 0x72, 0x65, 0x64, + 0x75, 0x74, 0x68, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x63, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x73, 0x2e, 0x4f, 0x61, 0x75, 0x74, 0x68, 0x32, 0x48, 0x00, - 0x52, 0x05, 0x6f, 0x61, 0x75, 0x74, 0x68, 0x12, 0x1a, 0x0a, 0x08, 0x63, 0x68, 0x61, 0x6e, 0x6e, - 0x65, 0x6c, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x09, 0x52, 0x08, 0x63, 0x68, 0x61, 0x6e, 0x6e, - 0x65, 0x6c, 0x73, 0x12, 0x1e, 0x0a, 0x0a, 0x69, 0x67, 0x6e, 0x6f, 0x72, 0x65, 0x4c, 0x69, 0x73, - 0x74, 0x18, 0x05, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0a, 0x69, 0x67, 0x6e, 0x6f, 0x72, 0x65, 0x4c, - 0x69, 0x73, 0x74, 0x12, 0x19, 0x0a, 0x08, 0x74, 0x65, 0x61, 0x6d, 0x5f, 0x69, 0x64, 0x73, 0x18, - 0x06, 0x20, 0x03, 0x28, 0x09, 0x52, 0x07, 0x74, 0x65, 0x61, 0x6d, 0x49, 0x64, 0x73, 0x42, 0x0c, - 0x0a, 0x0a, 0x63, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x22, 0x8b, 0x02, 0x0a, - 0x0b, 0x41, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x6f, 0x72, 0x79, 0x12, 0x24, 0x0a, 0x08, - 0x65, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x08, - 0xfa, 0x42, 0x05, 0x72, 0x03, 0x90, 0x01, 0x01, 0x52, 0x08, 0x65, 0x6e, 0x64, 0x70, 0x6f, 0x69, - 0x6e, 0x74, 0x12, 0x37, 0x0a, 0x0a, 0x62, 0x61, 0x73, 0x69, 0x63, 0x5f, 0x61, 0x75, 0x74, 0x68, - 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x63, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, - 0x69, 0x61, 0x6c, 0x73, 0x2e, 0x42, 0x61, 0x73, 0x69, 0x63, 0x41, 0x75, 0x74, 0x68, 0x48, 0x00, - 0x52, 0x09, 0x62, 0x61, 0x73, 0x69, 0x63, 0x41, 0x75, 0x74, 0x68, 0x12, 0x23, 0x0a, 0x0c, 0x61, - 0x63, 0x63, 0x65, 0x73, 0x73, 0x5f, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, - 0x09, 0x48, 0x00, 0x52, 0x0b, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x54, 0x6f, 0x6b, 0x65, 0x6e, + 0x52, 0x05, 0x6f, 0x61, 0x75, 0x74, 0x68, 0x12, 0x16, 0x0a, 0x05, 0x74, 0x6f, 0x6b, 0x65, 0x6e, + 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x05, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x12, + 0x1a, 0x0a, 0x08, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, + 0x09, 0x52, 0x08, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x12, 0x27, 0x0a, 0x0f, 0x69, + 0x67, 0x6e, 0x6f, 0x72, 0x65, 0x5f, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x18, 0x07, + 0x20, 0x03, 0x28, 0x09, 0x52, 0x0e, 0x69, 0x67, 0x6e, 0x6f, 0x72, 0x65, 0x50, 0x72, 0x6f, 0x6a, + 0x65, 0x63, 0x74, 0x73, 0x12, 0x37, 0x0a, 0x18, 0x69, 0x6e, 0x73, 0x65, 0x63, 0x75, 0x72, 0x65, + 0x5f, 0x73, 0x6b, 0x69, 0x70, 0x5f, 0x76, 0x65, 0x72, 0x69, 0x66, 0x79, 0x5f, 0x74, 0x6c, 0x73, + 0x18, 0x08, 0x20, 0x01, 0x28, 0x08, 0x52, 0x15, 0x69, 0x6e, 0x73, 0x65, 0x63, 0x75, 0x72, 0x65, + 0x53, 0x6b, 0x69, 0x70, 0x56, 0x65, 0x72, 0x69, 0x66, 0x79, 0x54, 0x6c, 0x73, 0x42, 0x0c, 0x0a, + 0x0a, 0x63, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x22, 0x73, 0x0a, 0x19, 0x4e, + 0x50, 0x4d, 0x55, 0x6e, 0x61, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x65, + 0x64, 0x50, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x12, 0x48, 0x0a, 0x0f, 0x75, 0x6e, 0x61, 0x75, + 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x65, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x1c, 0x2e, 0x63, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x73, 0x2e, + 0x55, 0x6e, 0x61, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x65, 0x64, 0x48, + 0x00, 0x52, 0x0f, 0x75, 0x6e, 0x61, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, + 0x65, 0x64, 0x42, 0x0c, 0x0a, 0x0a, 0x63, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, + 0x22, 0x74, 0x0a, 0x1a, 0x50, 0x79, 0x50, 0x49, 0x55, 0x6e, 0x61, 0x75, 0x74, 0x68, 0x65, 0x6e, + 0x74, 0x69, 0x63, 0x61, 0x74, 0x65, 0x64, 0x50, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x12, 0x48, + 0x0a, 0x0f, 0x75, 0x6e, 0x61, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x65, + 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x63, 0x72, 0x65, 0x64, 0x65, 0x6e, + 0x74, 0x69, 0x61, 0x6c, 0x73, 0x2e, 0x55, 0x6e, 0x61, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, + 0x63, 0x61, 0x74, 0x65, 0x64, 0x48, 0x00, 0x52, 0x0f, 0x75, 0x6e, 0x61, 0x75, 0x74, 0x68, 0x65, + 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x65, 0x64, 0x42, 0x0c, 0x0a, 0x0a, 0x63, 0x72, 0x65, 0x64, + 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x22, 0x86, 0x03, 0x0a, 0x02, 0x53, 0x33, 0x12, 0x37, 0x0a, + 0x0a, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x16, 0x2e, 0x63, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x73, 0x2e, + 0x4b, 0x65, 0x79, 0x53, 0x65, 0x63, 0x72, 0x65, 0x74, 0x48, 0x00, 0x52, 0x09, 0x61, 0x63, 0x63, + 0x65, 0x73, 0x73, 0x4b, 0x65, 0x79, 0x12, 0x48, 0x0a, 0x0f, 0x75, 0x6e, 0x61, 0x75, 0x74, 0x68, + 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x65, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x1c, 0x2e, 0x63, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x73, 0x2e, 0x55, 0x6e, + 0x61, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x65, 0x64, 0x48, 0x00, 0x52, + 0x0f, 0x75, 0x6e, 0x61, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x65, 0x64, + 0x12, 0x4c, 0x0a, 0x11, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x5f, 0x65, 0x6e, 0x76, 0x69, 0x72, 0x6f, + 0x6e, 0x6d, 0x65, 0x6e, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x63, 0x72, + 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x73, 0x2e, 0x43, 0x6c, 0x6f, 0x75, 0x64, 0x45, + 0x6e, 0x76, 0x69, 0x72, 0x6f, 0x6e, 0x6d, 0x65, 0x6e, 0x74, 0x48, 0x00, 0x52, 0x10, 0x63, 0x6c, + 0x6f, 0x75, 0x64, 0x45, 0x6e, 0x76, 0x69, 0x72, 0x6f, 0x6e, 0x6d, 0x65, 0x6e, 0x74, 0x12, 0x49, + 0x0a, 0x0d, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x18, + 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x63, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, + 0x61, 0x6c, 0x73, 0x2e, 0x41, 0x57, 0x53, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x54, 0x6f, + 0x6b, 0x65, 0x6e, 0x53, 0x65, 0x63, 0x72, 0x65, 0x74, 0x48, 0x00, 0x52, 0x0c, 0x73, 0x65, 0x73, + 0x73, 0x69, 0x6f, 0x6e, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x12, 0x18, 0x0a, 0x07, 0x62, 0x75, 0x63, + 0x6b, 0x65, 0x74, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x09, 0x52, 0x07, 0x62, 0x75, 0x63, 0x6b, + 0x65, 0x74, 0x73, 0x12, 0x26, 0x0a, 0x0f, 0x6d, 0x61, 0x78, 0x5f, 0x6f, 0x62, 0x6a, 0x65, 0x63, + 0x74, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0d, 0x6d, 0x61, + 0x78, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x53, 0x69, 0x7a, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x72, + 0x6f, 0x6c, 0x65, 0x73, 0x18, 0x07, 0x20, 0x03, 0x28, 0x09, 0x52, 0x05, 0x72, 0x6f, 0x6c, 0x65, + 0x73, 0x42, 0x0c, 0x0a, 0x0a, 0x63, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x22, + 0xc3, 0x01, 0x0a, 0x05, 0x53, 0x6c, 0x61, 0x63, 0x6b, 0x12, 0x24, 0x0a, 0x08, 0x65, 0x6e, 0x64, + 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x08, 0xfa, 0x42, 0x05, + 0x72, 0x03, 0x90, 0x01, 0x01, 0x52, 0x08, 0x65, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x12, + 0x16, 0x0a, 0x05, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, + 0x52, 0x05, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x12, 0x32, 0x0a, 0x06, 0x74, 0x6f, 0x6b, 0x65, 0x6e, + 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x63, 0x72, 0x65, 0x64, 0x65, 0x6e, + 0x74, 0x69, 0x61, 0x6c, 0x73, 0x2e, 0x53, 0x6c, 0x61, 0x63, 0x6b, 0x54, 0x6f, 0x6b, 0x65, 0x6e, + 0x73, 0x48, 0x00, 0x52, 0x06, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x73, 0x12, 0x1a, 0x0a, 0x08, 0x63, + 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x09, 0x52, 0x08, 0x63, + 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x73, 0x12, 0x1e, 0x0a, 0x0a, 0x69, 0x67, 0x6e, 0x6f, 0x72, + 0x65, 0x4c, 0x69, 0x73, 0x74, 0x18, 0x04, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0a, 0x69, 0x67, 0x6e, + 0x6f, 0x72, 0x65, 0x4c, 0x69, 0x73, 0x74, 0x42, 0x0c, 0x0a, 0x0a, 0x63, 0x72, 0x65, 0x64, 0x65, + 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x22, 0x06, 0x0a, 0x04, 0x54, 0x65, 0x73, 0x74, 0x22, 0x31, 0x0a, + 0x09, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x6b, 0x69, 0x74, 0x65, 0x12, 0x16, 0x0a, 0x05, 0x74, 0x6f, + 0x6b, 0x65, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x05, 0x74, 0x6f, 0x6b, + 0x65, 0x6e, 0x42, 0x0c, 0x0a, 0x0a, 0x63, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, + 0x22, 0xdb, 0x01, 0x0a, 0x06, 0x47, 0x65, 0x72, 0x72, 0x69, 0x74, 0x12, 0x24, 0x0a, 0x08, 0x65, + 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x08, 0xfa, + 0x42, 0x05, 0x72, 0x03, 0x90, 0x01, 0x01, 0x52, 0x08, 0x65, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, + 0x74, 0x12, 0x37, 0x0a, 0x0a, 0x62, 0x61, 0x73, 0x69, 0x63, 0x5f, 0x61, 0x75, 0x74, 0x68, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x63, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, + 0x61, 0x6c, 0x73, 0x2e, 0x42, 0x61, 0x73, 0x69, 0x63, 0x41, 0x75, 0x74, 0x68, 0x48, 0x00, 0x52, + 0x09, 0x62, 0x61, 0x73, 0x69, 0x63, 0x41, 0x75, 0x74, 0x68, 0x12, 0x48, 0x0a, 0x0f, 0x75, 0x6e, + 0x61, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x65, 0x64, 0x18, 0x03, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x63, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, + 0x73, 0x2e, 0x55, 0x6e, 0x61, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x65, + 0x64, 0x48, 0x00, 0x52, 0x0f, 0x75, 0x6e, 0x61, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, + 0x61, 0x74, 0x65, 0x64, 0x12, 0x1a, 0x0a, 0x08, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x73, + 0x18, 0x04, 0x20, 0x03, 0x28, 0x09, 0x52, 0x08, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x73, + 0x42, 0x0c, 0x0a, 0x0a, 0x63, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x22, 0xde, + 0x01, 0x0a, 0x07, 0x4a, 0x65, 0x6e, 0x6b, 0x69, 0x6e, 0x73, 0x12, 0x24, 0x0a, 0x08, 0x65, 0x6e, + 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x08, 0xfa, 0x42, + 0x05, 0x72, 0x03, 0x90, 0x01, 0x01, 0x52, 0x08, 0x65, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, + 0x12, 0x37, 0x0a, 0x0a, 0x62, 0x61, 0x73, 0x69, 0x63, 0x5f, 0x61, 0x75, 0x74, 0x68, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x63, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, + 0x6c, 0x73, 0x2e, 0x42, 0x61, 0x73, 0x69, 0x63, 0x41, 0x75, 0x74, 0x68, 0x48, 0x00, 0x52, 0x09, + 0x62, 0x61, 0x73, 0x69, 0x63, 0x41, 0x75, 0x74, 0x68, 0x12, 0x2d, 0x0a, 0x06, 0x68, 0x65, 0x61, + 0x64, 0x65, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x63, 0x72, 0x65, 0x64, + 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x73, 0x2e, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x48, 0x00, + 0x52, 0x06, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x12, 0x37, 0x0a, 0x18, 0x69, 0x6e, 0x73, 0x65, + 0x63, 0x75, 0x72, 0x65, 0x5f, 0x73, 0x6b, 0x69, 0x70, 0x5f, 0x76, 0x65, 0x72, 0x69, 0x66, 0x79, + 0x5f, 0x74, 0x6c, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x15, 0x69, 0x6e, 0x73, 0x65, + 0x63, 0x75, 0x72, 0x65, 0x53, 0x6b, 0x69, 0x70, 0x56, 0x65, 0x72, 0x69, 0x66, 0x79, 0x54, 0x6c, + 0x73, 0x42, 0x0c, 0x0a, 0x0a, 0x63, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x22, + 0x9f, 0x02, 0x0a, 0x05, 0x54, 0x65, 0x61, 0x6d, 0x73, 0x12, 0x24, 0x0a, 0x08, 0x65, 0x6e, 0x64, + 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x08, 0xfa, 0x42, 0x05, + 0x72, 0x03, 0x90, 0x01, 0x01, 0x52, 0x08, 0x65, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x12, + 0x16, 0x0a, 0x05, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, + 0x52, 0x05, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x12, 0x46, 0x0a, 0x0d, 0x61, 0x75, 0x74, 0x68, 0x65, + 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x65, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1e, + 0x2e, 0x63, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x73, 0x2e, 0x43, 0x6c, 0x69, + 0x65, 0x6e, 0x74, 0x43, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x73, 0x48, 0x00, + 0x52, 0x0d, 0x61, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x65, 0x64, 0x12, + 0x2b, 0x0a, 0x05, 0x6f, 0x61, 0x75, 0x74, 0x68, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, + 0x2e, 0x63, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x73, 0x2e, 0x4f, 0x61, 0x75, + 0x74, 0x68, 0x32, 0x48, 0x00, 0x52, 0x05, 0x6f, 0x61, 0x75, 0x74, 0x68, 0x12, 0x1a, 0x0a, 0x08, + 0x63, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x09, 0x52, 0x08, + 0x63, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x73, 0x12, 0x1e, 0x0a, 0x0a, 0x69, 0x67, 0x6e, 0x6f, + 0x72, 0x65, 0x4c, 0x69, 0x73, 0x74, 0x18, 0x05, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0a, 0x69, 0x67, + 0x6e, 0x6f, 0x72, 0x65, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x19, 0x0a, 0x08, 0x74, 0x65, 0x61, 0x6d, + 0x5f, 0x69, 0x64, 0x73, 0x18, 0x06, 0x20, 0x03, 0x28, 0x09, 0x52, 0x07, 0x74, 0x65, 0x61, 0x6d, + 0x49, 0x64, 0x73, 0x42, 0x0c, 0x0a, 0x0a, 0x63, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, + 0x6c, 0x22, 0x8b, 0x02, 0x0a, 0x0b, 0x41, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x6f, 0x72, + 0x79, 0x12, 0x24, 0x0a, 0x08, 0x65, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x09, 0x42, 0x08, 0xfa, 0x42, 0x05, 0x72, 0x03, 0x90, 0x01, 0x01, 0x52, 0x08, 0x65, + 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x12, 0x37, 0x0a, 0x0a, 0x62, 0x61, 0x73, 0x69, 0x63, + 0x5f, 0x61, 0x75, 0x74, 0x68, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x63, 0x72, + 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x73, 0x2e, 0x42, 0x61, 0x73, 0x69, 0x63, 0x41, + 0x75, 0x74, 0x68, 0x48, 0x00, 0x52, 0x09, 0x62, 0x61, 0x73, 0x69, 0x63, 0x41, 0x75, 0x74, 0x68, + 0x12, 0x23, 0x0a, 0x0c, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x5f, 0x74, 0x6f, 0x6b, 0x65, 0x6e, + 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x0b, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, + 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x12, 0x22, 0x0a, 0x0c, 0x72, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, + 0x6f, 0x72, 0x69, 0x65, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0c, 0x72, 0x65, 0x70, + 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x69, 0x65, 0x73, 0x12, 0x23, 0x0a, 0x0d, 0x69, 0x6e, 0x63, + 0x6c, 0x75, 0x64, 0x65, 0x5f, 0x70, 0x61, 0x74, 0x68, 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, 0x09, + 0x52, 0x0c, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x50, 0x61, 0x74, 0x68, 0x73, 0x12, 0x21, + 0x0a, 0x0c, 0x69, 0x67, 0x6e, 0x6f, 0x72, 0x65, 0x5f, 0x70, 0x61, 0x74, 0x68, 0x73, 0x18, 0x06, + 0x20, 0x03, 0x28, 0x09, 0x52, 0x0b, 0x69, 0x67, 0x6e, 0x6f, 0x72, 0x65, 0x50, 0x61, 0x74, 0x68, + 0x73, 0x42, 0x0c, 0x0a, 0x0a, 0x63, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x22, + 0x94, 0x01, 0x0a, 0x06, 0x53, 0x79, 0x73, 0x6c, 0x6f, 0x67, 0x12, 0x1a, 0x0a, 0x08, 0x70, 0x72, + 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x70, 0x72, + 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x12, 0x24, 0x0a, 0x0d, 0x6c, 0x69, 0x73, 0x74, 0x65, 0x6e, + 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x6c, + 0x69, 0x73, 0x74, 0x65, 0x6e, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x18, 0x0a, 0x07, + 0x74, 0x6c, 0x73, 0x43, 0x65, 0x72, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x74, + 0x6c, 0x73, 0x43, 0x65, 0x72, 0x74, 0x12, 0x16, 0x0a, 0x06, 0x74, 0x6c, 0x73, 0x4b, 0x65, 0x79, + 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x74, 0x6c, 0x73, 0x4b, 0x65, 0x79, 0x12, 0x16, + 0x0a, 0x06, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, + 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x22, 0xd6, 0x01, 0x0a, 0x15, 0x50, 0x75, 0x62, 0x6c, 0x69, + 0x63, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x4d, 0x6f, 0x6e, 0x69, 0x74, 0x6f, 0x72, 0x69, 0x6e, 0x67, + 0x12, 0x48, 0x0a, 0x0f, 0x75, 0x6e, 0x61, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, + 0x74, 0x65, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x63, 0x72, 0x65, 0x64, + 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x73, 0x2e, 0x55, 0x6e, 0x61, 0x75, 0x74, 0x68, 0x65, 0x6e, + 0x74, 0x69, 0x63, 0x61, 0x74, 0x65, 0x64, 0x48, 0x00, 0x52, 0x0f, 0x75, 0x6e, 0x61, 0x75, 0x74, + 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x65, 0x64, 0x12, 0x16, 0x0a, 0x06, 0x64, 0x6f, + 0x6d, 0x61, 0x69, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x64, 0x6f, 0x6d, 0x61, + 0x69, 0x6e, 0x12, 0x1b, 0x0a, 0x09, 0x6d, 0x61, 0x78, 0x5f, 0x64, 0x65, 0x70, 0x74, 0x68, 0x18, + 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x08, 0x6d, 0x61, 0x78, 0x44, 0x65, 0x70, 0x74, 0x68, 0x12, + 0x30, 0x0a, 0x05, 0x73, 0x69, 0x6e, 0x63, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, + 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, + 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x05, 0x73, 0x69, 0x6e, 0x63, + 0x65, 0x42, 0x0c, 0x0a, 0x0a, 0x63, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x22, + 0x51, 0x0a, 0x0d, 0x53, 0x6c, 0x61, 0x63, 0x6b, 0x52, 0x65, 0x61, 0x6c, 0x74, 0x69, 0x6d, 0x65, + 0x12, 0x32, 0x0a, 0x06, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x18, 0x2e, 0x63, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x73, 0x2e, 0x53, + 0x6c, 0x61, 0x63, 0x6b, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x73, 0x48, 0x00, 0x52, 0x06, 0x74, 0x6f, + 0x6b, 0x65, 0x6e, 0x73, 0x42, 0x0c, 0x0a, 0x0a, 0x63, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, + 0x61, 0x6c, 0x22, 0x62, 0x0a, 0x0a, 0x53, 0x68, 0x61, 0x72, 0x65, 0x70, 0x6f, 0x69, 0x6e, 0x74, + 0x12, 0x2b, 0x0a, 0x05, 0x6f, 0x61, 0x75, 0x74, 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x13, 0x2e, 0x63, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x73, 0x2e, 0x4f, 0x61, + 0x75, 0x74, 0x68, 0x32, 0x48, 0x00, 0x52, 0x05, 0x6f, 0x61, 0x75, 0x74, 0x68, 0x12, 0x19, 0x0a, + 0x08, 0x73, 0x69, 0x74, 0x65, 0x5f, 0x75, 0x72, 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x07, 0x73, 0x69, 0x74, 0x65, 0x55, 0x72, 0x6c, 0x42, 0x0c, 0x0a, 0x0a, 0x63, 0x72, 0x65, 0x64, + 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x22, 0xa7, 0x03, 0x0a, 0x0a, 0x41, 0x7a, 0x75, 0x72, 0x65, + 0x52, 0x65, 0x70, 0x6f, 0x73, 0x12, 0x24, 0x0a, 0x08, 0x65, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, + 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x08, 0xfa, 0x42, 0x05, 0x72, 0x03, 0x90, 0x01, + 0x01, 0x52, 0x08, 0x65, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x12, 0x16, 0x0a, 0x05, 0x74, + 0x6f, 0x6b, 0x65, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x05, 0x74, 0x6f, + 0x6b, 0x65, 0x6e, 0x12, 0x2b, 0x0a, 0x05, 0x6f, 0x61, 0x75, 0x74, 0x68, 0x18, 0x03, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x63, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x73, + 0x2e, 0x4f, 0x61, 0x75, 0x74, 0x68, 0x32, 0x48, 0x00, 0x52, 0x05, 0x6f, 0x61, 0x75, 0x74, 0x68, 0x12, 0x22, 0x0a, 0x0c, 0x72, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x69, 0x65, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0c, 0x72, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, - 0x72, 0x69, 0x65, 0x73, 0x12, 0x23, 0x0a, 0x0d, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x5f, - 0x70, 0x61, 0x74, 0x68, 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0c, 0x69, 0x6e, 0x63, - 0x6c, 0x75, 0x64, 0x65, 0x50, 0x61, 0x74, 0x68, 0x73, 0x12, 0x21, 0x0a, 0x0c, 0x69, 0x67, 0x6e, - 0x6f, 0x72, 0x65, 0x5f, 0x70, 0x61, 0x74, 0x68, 0x73, 0x18, 0x06, 0x20, 0x03, 0x28, 0x09, 0x52, - 0x0b, 0x69, 0x67, 0x6e, 0x6f, 0x72, 0x65, 0x50, 0x61, 0x74, 0x68, 0x73, 0x42, 0x0c, 0x0a, 0x0a, - 0x63, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x22, 0x94, 0x01, 0x0a, 0x06, 0x53, - 0x79, 0x73, 0x6c, 0x6f, 0x67, 0x12, 0x1a, 0x0a, 0x08, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, - 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, - 0x6c, 0x12, 0x24, 0x0a, 0x0d, 0x6c, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x41, 0x64, 0x64, 0x72, 0x65, - 0x73, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x6c, 0x69, 0x73, 0x74, 0x65, 0x6e, - 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x18, 0x0a, 0x07, 0x74, 0x6c, 0x73, 0x43, 0x65, - 0x72, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x74, 0x6c, 0x73, 0x43, 0x65, 0x72, - 0x74, 0x12, 0x16, 0x0a, 0x06, 0x74, 0x6c, 0x73, 0x4b, 0x65, 0x79, 0x18, 0x04, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x06, 0x74, 0x6c, 0x73, 0x4b, 0x65, 0x79, 0x12, 0x16, 0x0a, 0x06, 0x66, 0x6f, 0x72, - 0x6d, 0x61, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x66, 0x6f, 0x72, 0x6d, 0x61, - 0x74, 0x22, 0xd6, 0x01, 0x0a, 0x15, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x45, 0x76, 0x65, 0x6e, - 0x74, 0x4d, 0x6f, 0x6e, 0x69, 0x74, 0x6f, 0x72, 0x69, 0x6e, 0x67, 0x12, 0x48, 0x0a, 0x0f, 0x75, - 0x6e, 0x61, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x65, 0x64, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x63, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, - 0x6c, 0x73, 0x2e, 0x55, 0x6e, 0x61, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, - 0x65, 0x64, 0x48, 0x00, 0x52, 0x0f, 0x75, 0x6e, 0x61, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, - 0x63, 0x61, 0x74, 0x65, 0x64, 0x12, 0x16, 0x0a, 0x06, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x18, - 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x12, 0x1b, 0x0a, - 0x09, 0x6d, 0x61, 0x78, 0x5f, 0x64, 0x65, 0x70, 0x74, 0x68, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, - 0x52, 0x08, 0x6d, 0x61, 0x78, 0x44, 0x65, 0x70, 0x74, 0x68, 0x12, 0x30, 0x0a, 0x05, 0x73, 0x69, - 0x6e, 0x63, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, - 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, - 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x05, 0x73, 0x69, 0x6e, 0x63, 0x65, 0x42, 0x0c, 0x0a, 0x0a, - 0x63, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x22, 0x51, 0x0a, 0x0d, 0x53, 0x6c, - 0x61, 0x63, 0x6b, 0x52, 0x65, 0x61, 0x6c, 0x74, 0x69, 0x6d, 0x65, 0x12, 0x32, 0x0a, 0x06, 0x74, - 0x6f, 0x6b, 0x65, 0x6e, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x63, 0x72, - 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x73, 0x2e, 0x53, 0x6c, 0x61, 0x63, 0x6b, 0x54, - 0x6f, 0x6b, 0x65, 0x6e, 0x73, 0x48, 0x00, 0x52, 0x06, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x73, 0x42, - 0x0c, 0x0a, 0x0a, 0x63, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x22, 0x62, 0x0a, - 0x0a, 0x53, 0x68, 0x61, 0x72, 0x65, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x12, 0x2b, 0x0a, 0x05, 0x6f, - 0x61, 0x75, 0x74, 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x63, 0x72, 0x65, - 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x73, 0x2e, 0x4f, 0x61, 0x75, 0x74, 0x68, 0x32, 0x48, - 0x00, 0x52, 0x05, 0x6f, 0x61, 0x75, 0x74, 0x68, 0x12, 0x19, 0x0a, 0x08, 0x73, 0x69, 0x74, 0x65, - 0x5f, 0x75, 0x72, 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x73, 0x69, 0x74, 0x65, - 0x55, 0x72, 0x6c, 0x42, 0x0c, 0x0a, 0x0a, 0x63, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, - 0x6c, 0x22, 0xa7, 0x03, 0x0a, 0x0a, 0x41, 0x7a, 0x75, 0x72, 0x65, 0x52, 0x65, 0x70, 0x6f, 0x73, - 0x12, 0x24, 0x0a, 0x08, 0x65, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x09, 0x42, 0x08, 0xfa, 0x42, 0x05, 0x72, 0x03, 0x90, 0x01, 0x01, 0x52, 0x08, 0x65, 0x6e, - 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x12, 0x16, 0x0a, 0x05, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x18, - 0x02, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x05, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x12, 0x2b, - 0x0a, 0x05, 0x6f, 0x61, 0x75, 0x74, 0x68, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, - 0x63, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x73, 0x2e, 0x4f, 0x61, 0x75, 0x74, - 0x68, 0x32, 0x48, 0x00, 0x52, 0x05, 0x6f, 0x61, 0x75, 0x74, 0x68, 0x12, 0x22, 0x0a, 0x0c, 0x72, - 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x69, 0x65, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, - 0x09, 0x52, 0x0c, 0x72, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x69, 0x65, 0x73, 0x12, - 0x24, 0x0a, 0x0d, 0x6f, 0x72, 0x67, 0x61, 0x6e, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, - 0x18, 0x05, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0d, 0x6f, 0x72, 0x67, 0x61, 0x6e, 0x69, 0x7a, 0x61, - 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x1a, 0x0a, 0x08, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, - 0x73, 0x18, 0x06, 0x20, 0x03, 0x28, 0x09, 0x52, 0x08, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, - 0x73, 0x12, 0x22, 0x0a, 0x0c, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x46, 0x6f, 0x72, 0x6b, - 0x73, 0x18, 0x07, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0c, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, - 0x46, 0x6f, 0x72, 0x6b, 0x73, 0x12, 0x20, 0x0a, 0x0b, 0x69, 0x67, 0x6e, 0x6f, 0x72, 0x65, 0x52, - 0x65, 0x70, 0x6f, 0x73, 0x18, 0x08, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0b, 0x69, 0x67, 0x6e, 0x6f, - 0x72, 0x65, 0x52, 0x65, 0x70, 0x6f, 0x73, 0x12, 0x22, 0x0a, 0x0c, 0x69, 0x6e, 0x63, 0x6c, 0x75, - 0x64, 0x65, 0x52, 0x65, 0x70, 0x6f, 0x73, 0x18, 0x09, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0c, 0x69, - 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x52, 0x65, 0x70, 0x6f, 0x73, 0x12, 0x28, 0x0a, 0x0f, 0x69, - 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x50, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x18, 0x0a, - 0x20, 0x03, 0x28, 0x09, 0x52, 0x0f, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x50, 0x72, 0x6f, - 0x6a, 0x65, 0x63, 0x74, 0x73, 0x12, 0x26, 0x0a, 0x0e, 0x69, 0x67, 0x6e, 0x6f, 0x72, 0x65, 0x50, - 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x18, 0x0b, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0e, 0x69, - 0x67, 0x6e, 0x6f, 0x72, 0x65, 0x50, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x42, 0x0c, 0x0a, - 0x0a, 0x63, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x2a, 0x84, 0x07, 0x0a, 0x0a, - 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x54, 0x79, 0x70, 0x65, 0x12, 0x1d, 0x0a, 0x19, 0x53, 0x4f, + 0x72, 0x69, 0x65, 0x73, 0x12, 0x24, 0x0a, 0x0d, 0x6f, 0x72, 0x67, 0x61, 0x6e, 0x69, 0x7a, 0x61, + 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0d, 0x6f, 0x72, 0x67, + 0x61, 0x6e, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x1a, 0x0a, 0x08, 0x70, 0x72, + 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x18, 0x06, 0x20, 0x03, 0x28, 0x09, 0x52, 0x08, 0x70, 0x72, + 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x12, 0x22, 0x0a, 0x0c, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, + 0x65, 0x46, 0x6f, 0x72, 0x6b, 0x73, 0x18, 0x07, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0c, 0x69, 0x6e, + 0x63, 0x6c, 0x75, 0x64, 0x65, 0x46, 0x6f, 0x72, 0x6b, 0x73, 0x12, 0x20, 0x0a, 0x0b, 0x69, 0x67, + 0x6e, 0x6f, 0x72, 0x65, 0x52, 0x65, 0x70, 0x6f, 0x73, 0x18, 0x08, 0x20, 0x03, 0x28, 0x09, 0x52, + 0x0b, 0x69, 0x67, 0x6e, 0x6f, 0x72, 0x65, 0x52, 0x65, 0x70, 0x6f, 0x73, 0x12, 0x22, 0x0a, 0x0c, + 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x52, 0x65, 0x70, 0x6f, 0x73, 0x18, 0x09, 0x20, 0x03, + 0x28, 0x09, 0x52, 0x0c, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x52, 0x65, 0x70, 0x6f, 0x73, + 0x12, 0x28, 0x0a, 0x0f, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x50, 0x72, 0x6f, 0x6a, 0x65, + 0x63, 0x74, 0x73, 0x18, 0x0a, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0f, 0x69, 0x6e, 0x63, 0x6c, 0x75, + 0x64, 0x65, 0x50, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x12, 0x26, 0x0a, 0x0e, 0x69, 0x67, + 0x6e, 0x6f, 0x72, 0x65, 0x50, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x18, 0x0b, 0x20, 0x03, + 0x28, 0x09, 0x52, 0x0e, 0x69, 0x67, 0x6e, 0x6f, 0x72, 0x65, 0x50, 0x72, 0x6f, 0x6a, 0x65, 0x63, + 0x74, 0x73, 0x42, 0x0c, 0x0a, 0x0a, 0x63, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, + 0x2a, 0x84, 0x07, 0x0a, 0x0a, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x54, 0x79, 0x70, 0x65, 0x12, + 0x1d, 0x0a, 0x19, 0x53, 0x4f, 0x55, 0x52, 0x43, 0x45, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x41, + 0x5a, 0x55, 0x52, 0x45, 0x5f, 0x53, 0x54, 0x4f, 0x52, 0x41, 0x47, 0x45, 0x10, 0x00, 0x12, 0x19, + 0x0a, 0x15, 0x53, 0x4f, 0x55, 0x52, 0x43, 0x45, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x42, 0x49, + 0x54, 0x42, 0x55, 0x43, 0x4b, 0x45, 0x54, 0x10, 0x01, 0x12, 0x18, 0x0a, 0x14, 0x53, 0x4f, 0x55, + 0x52, 0x43, 0x45, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x43, 0x49, 0x52, 0x43, 0x4c, 0x45, 0x43, + 0x49, 0x10, 0x02, 0x12, 0x1a, 0x0a, 0x16, 0x53, 0x4f, 0x55, 0x52, 0x43, 0x45, 0x5f, 0x54, 0x59, + 0x50, 0x45, 0x5f, 0x43, 0x4f, 0x4e, 0x46, 0x4c, 0x55, 0x45, 0x4e, 0x43, 0x45, 0x10, 0x03, 0x12, + 0x16, 0x0a, 0x12, 0x53, 0x4f, 0x55, 0x52, 0x43, 0x45, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x44, + 0x4f, 0x43, 0x4b, 0x45, 0x52, 0x10, 0x04, 0x12, 0x13, 0x0a, 0x0f, 0x53, 0x4f, 0x55, 0x52, 0x43, + 0x45, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x45, 0x43, 0x52, 0x10, 0x05, 0x12, 0x13, 0x0a, 0x0f, + 0x53, 0x4f, 0x55, 0x52, 0x43, 0x45, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x47, 0x43, 0x53, 0x10, + 0x06, 0x12, 0x16, 0x0a, 0x12, 0x53, 0x4f, 0x55, 0x52, 0x43, 0x45, 0x5f, 0x54, 0x59, 0x50, 0x45, + 0x5f, 0x47, 0x49, 0x54, 0x48, 0x55, 0x42, 0x10, 0x07, 0x12, 0x1a, 0x0a, 0x16, 0x53, 0x4f, 0x55, + 0x52, 0x43, 0x45, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x50, 0x55, 0x42, 0x4c, 0x49, 0x43, 0x5f, + 0x47, 0x49, 0x54, 0x10, 0x08, 0x12, 0x16, 0x0a, 0x12, 0x53, 0x4f, 0x55, 0x52, 0x43, 0x45, 0x5f, + 0x54, 0x59, 0x50, 0x45, 0x5f, 0x47, 0x49, 0x54, 0x4c, 0x41, 0x42, 0x10, 0x09, 0x12, 0x14, 0x0a, + 0x10, 0x53, 0x4f, 0x55, 0x52, 0x43, 0x45, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x4a, 0x49, 0x52, + 0x41, 0x10, 0x0a, 0x12, 0x24, 0x0a, 0x20, 0x53, 0x4f, 0x55, 0x52, 0x43, 0x45, 0x5f, 0x54, 0x59, + 0x50, 0x45, 0x5f, 0x4e, 0x50, 0x4d, 0x5f, 0x55, 0x4e, 0x41, 0x55, 0x54, 0x48, 0x44, 0x5f, 0x50, + 0x41, 0x43, 0x4b, 0x41, 0x47, 0x45, 0x53, 0x10, 0x0b, 0x12, 0x25, 0x0a, 0x21, 0x53, 0x4f, 0x55, + 0x52, 0x43, 0x45, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x50, 0x59, 0x50, 0x49, 0x5f, 0x55, 0x4e, + 0x41, 0x55, 0x54, 0x48, 0x44, 0x5f, 0x50, 0x41, 0x43, 0x4b, 0x41, 0x47, 0x45, 0x53, 0x10, 0x0c, + 0x12, 0x12, 0x0a, 0x0e, 0x53, 0x4f, 0x55, 0x52, 0x43, 0x45, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, + 0x53, 0x33, 0x10, 0x0d, 0x12, 0x15, 0x0a, 0x11, 0x53, 0x4f, 0x55, 0x52, 0x43, 0x45, 0x5f, 0x54, + 0x59, 0x50, 0x45, 0x5f, 0x53, 0x4c, 0x41, 0x43, 0x4b, 0x10, 0x0e, 0x12, 0x1a, 0x0a, 0x16, 0x53, + 0x4f, 0x55, 0x52, 0x43, 0x45, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x46, 0x49, 0x4c, 0x45, 0x53, + 0x59, 0x53, 0x54, 0x45, 0x4d, 0x10, 0x0f, 0x12, 0x13, 0x0a, 0x0f, 0x53, 0x4f, 0x55, 0x52, 0x43, + 0x45, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x47, 0x49, 0x54, 0x10, 0x10, 0x12, 0x14, 0x0a, 0x10, + 0x53, 0x4f, 0x55, 0x52, 0x43, 0x45, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x54, 0x45, 0x53, 0x54, + 0x10, 0x11, 0x12, 0x1b, 0x0a, 0x17, 0x53, 0x4f, 0x55, 0x52, 0x43, 0x45, 0x5f, 0x54, 0x59, 0x50, + 0x45, 0x5f, 0x53, 0x33, 0x5f, 0x55, 0x4e, 0x41, 0x55, 0x54, 0x48, 0x45, 0x44, 0x10, 0x12, 0x12, + 0x2a, 0x0a, 0x26, 0x53, 0x4f, 0x55, 0x52, 0x43, 0x45, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x47, + 0x49, 0x54, 0x48, 0x55, 0x42, 0x5f, 0x55, 0x4e, 0x41, 0x55, 0x54, 0x48, 0x45, 0x4e, 0x54, 0x49, + 0x43, 0x41, 0x54, 0x45, 0x44, 0x5f, 0x4f, 0x52, 0x47, 0x10, 0x13, 0x12, 0x19, 0x0a, 0x15, 0x53, + 0x4f, 0x55, 0x52, 0x43, 0x45, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x42, 0x55, 0x49, 0x4c, 0x44, + 0x4b, 0x49, 0x54, 0x45, 0x10, 0x14, 0x12, 0x16, 0x0a, 0x12, 0x53, 0x4f, 0x55, 0x52, 0x43, 0x45, + 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x47, 0x45, 0x52, 0x52, 0x49, 0x54, 0x10, 0x15, 0x12, 0x17, + 0x0a, 0x13, 0x53, 0x4f, 0x55, 0x52, 0x43, 0x45, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x4a, 0x45, + 0x4e, 0x4b, 0x49, 0x4e, 0x53, 0x10, 0x16, 0x12, 0x15, 0x0a, 0x11, 0x53, 0x4f, 0x55, 0x52, 0x43, + 0x45, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x54, 0x45, 0x41, 0x4d, 0x53, 0x10, 0x17, 0x12, 0x21, + 0x0a, 0x1d, 0x53, 0x4f, 0x55, 0x52, 0x43, 0x45, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x4a, 0x46, + 0x52, 0x4f, 0x47, 0x5f, 0x41, 0x52, 0x54, 0x49, 0x46, 0x41, 0x43, 0x54, 0x4f, 0x52, 0x59, 0x10, + 0x18, 0x12, 0x16, 0x0a, 0x12, 0x53, 0x4f, 0x55, 0x52, 0x43, 0x45, 0x5f, 0x54, 0x59, 0x50, 0x45, + 0x5f, 0x53, 0x59, 0x53, 0x4c, 0x4f, 0x47, 0x10, 0x19, 0x12, 0x27, 0x0a, 0x23, 0x53, 0x4f, 0x55, + 0x52, 0x43, 0x45, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x50, 0x55, 0x42, 0x4c, 0x49, 0x43, 0x5f, + 0x45, 0x56, 0x45, 0x4e, 0x54, 0x5f, 0x4d, 0x4f, 0x4e, 0x49, 0x54, 0x4f, 0x52, 0x49, 0x4e, 0x47, + 0x10, 0x1a, 0x12, 0x1e, 0x0a, 0x1a, 0x53, 0x4f, 0x55, 0x52, 0x43, 0x45, 0x5f, 0x54, 0x59, 0x50, + 0x45, 0x5f, 0x53, 0x4c, 0x41, 0x43, 0x4b, 0x5f, 0x52, 0x45, 0x41, 0x4c, 0x54, 0x49, 0x4d, 0x45, + 0x10, 0x1b, 0x12, 0x1c, 0x0a, 0x18, 0x53, 0x4f, 0x55, 0x52, 0x43, 0x45, 0x5f, 0x54, 0x59, 0x50, + 0x45, 0x5f, 0x47, 0x4f, 0x4f, 0x47, 0x4c, 0x45, 0x5f, 0x44, 0x52, 0x49, 0x56, 0x45, 0x10, 0x1c, + 0x12, 0x1a, 0x0a, 0x16, 0x53, 0x4f, 0x55, 0x52, 0x43, 0x45, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, + 0x53, 0x48, 0x41, 0x52, 0x45, 0x50, 0x4f, 0x49, 0x4e, 0x54, 0x10, 0x1d, 0x12, 0x1c, 0x0a, 0x18, + 0x53, 0x4f, 0x55, 0x52, 0x43, 0x45, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x47, 0x43, 0x53, 0x5f, + 0x55, 0x4e, 0x41, 0x55, 0x54, 0x48, 0x45, 0x44, 0x10, 0x1e, 0x12, 0x1b, 0x0a, 0x17, 0x53, 0x4f, 0x55, 0x52, 0x43, 0x45, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x41, 0x5a, 0x55, 0x52, 0x45, 0x5f, - 0x53, 0x54, 0x4f, 0x52, 0x41, 0x47, 0x45, 0x10, 0x00, 0x12, 0x19, 0x0a, 0x15, 0x53, 0x4f, 0x55, - 0x52, 0x43, 0x45, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x42, 0x49, 0x54, 0x42, 0x55, 0x43, 0x4b, - 0x45, 0x54, 0x10, 0x01, 0x12, 0x18, 0x0a, 0x14, 0x53, 0x4f, 0x55, 0x52, 0x43, 0x45, 0x5f, 0x54, - 0x59, 0x50, 0x45, 0x5f, 0x43, 0x49, 0x52, 0x43, 0x4c, 0x45, 0x43, 0x49, 0x10, 0x02, 0x12, 0x1a, - 0x0a, 0x16, 0x53, 0x4f, 0x55, 0x52, 0x43, 0x45, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x43, 0x4f, - 0x4e, 0x46, 0x4c, 0x55, 0x45, 0x4e, 0x43, 0x45, 0x10, 0x03, 0x12, 0x16, 0x0a, 0x12, 0x53, 0x4f, - 0x55, 0x52, 0x43, 0x45, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x44, 0x4f, 0x43, 0x4b, 0x45, 0x52, - 0x10, 0x04, 0x12, 0x13, 0x0a, 0x0f, 0x53, 0x4f, 0x55, 0x52, 0x43, 0x45, 0x5f, 0x54, 0x59, 0x50, - 0x45, 0x5f, 0x45, 0x43, 0x52, 0x10, 0x05, 0x12, 0x13, 0x0a, 0x0f, 0x53, 0x4f, 0x55, 0x52, 0x43, - 0x45, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x47, 0x43, 0x53, 0x10, 0x06, 0x12, 0x16, 0x0a, 0x12, - 0x53, 0x4f, 0x55, 0x52, 0x43, 0x45, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x47, 0x49, 0x54, 0x48, - 0x55, 0x42, 0x10, 0x07, 0x12, 0x1a, 0x0a, 0x16, 0x53, 0x4f, 0x55, 0x52, 0x43, 0x45, 0x5f, 0x54, - 0x59, 0x50, 0x45, 0x5f, 0x50, 0x55, 0x42, 0x4c, 0x49, 0x43, 0x5f, 0x47, 0x49, 0x54, 0x10, 0x08, - 0x12, 0x16, 0x0a, 0x12, 0x53, 0x4f, 0x55, 0x52, 0x43, 0x45, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, - 0x47, 0x49, 0x54, 0x4c, 0x41, 0x42, 0x10, 0x09, 0x12, 0x14, 0x0a, 0x10, 0x53, 0x4f, 0x55, 0x52, - 0x43, 0x45, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x4a, 0x49, 0x52, 0x41, 0x10, 0x0a, 0x12, 0x24, - 0x0a, 0x20, 0x53, 0x4f, 0x55, 0x52, 0x43, 0x45, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x4e, 0x50, - 0x4d, 0x5f, 0x55, 0x4e, 0x41, 0x55, 0x54, 0x48, 0x44, 0x5f, 0x50, 0x41, 0x43, 0x4b, 0x41, 0x47, - 0x45, 0x53, 0x10, 0x0b, 0x12, 0x25, 0x0a, 0x21, 0x53, 0x4f, 0x55, 0x52, 0x43, 0x45, 0x5f, 0x54, - 0x59, 0x50, 0x45, 0x5f, 0x50, 0x59, 0x50, 0x49, 0x5f, 0x55, 0x4e, 0x41, 0x55, 0x54, 0x48, 0x44, - 0x5f, 0x50, 0x41, 0x43, 0x4b, 0x41, 0x47, 0x45, 0x53, 0x10, 0x0c, 0x12, 0x12, 0x0a, 0x0e, 0x53, - 0x4f, 0x55, 0x52, 0x43, 0x45, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x53, 0x33, 0x10, 0x0d, 0x12, - 0x15, 0x0a, 0x11, 0x53, 0x4f, 0x55, 0x52, 0x43, 0x45, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x53, - 0x4c, 0x41, 0x43, 0x4b, 0x10, 0x0e, 0x12, 0x1a, 0x0a, 0x16, 0x53, 0x4f, 0x55, 0x52, 0x43, 0x45, - 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x46, 0x49, 0x4c, 0x45, 0x53, 0x59, 0x53, 0x54, 0x45, 0x4d, - 0x10, 0x0f, 0x12, 0x13, 0x0a, 0x0f, 0x53, 0x4f, 0x55, 0x52, 0x43, 0x45, 0x5f, 0x54, 0x59, 0x50, - 0x45, 0x5f, 0x47, 0x49, 0x54, 0x10, 0x10, 0x12, 0x14, 0x0a, 0x10, 0x53, 0x4f, 0x55, 0x52, 0x43, - 0x45, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x54, 0x45, 0x53, 0x54, 0x10, 0x11, 0x12, 0x1b, 0x0a, - 0x17, 0x53, 0x4f, 0x55, 0x52, 0x43, 0x45, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x53, 0x33, 0x5f, - 0x55, 0x4e, 0x41, 0x55, 0x54, 0x48, 0x45, 0x44, 0x10, 0x12, 0x12, 0x2a, 0x0a, 0x26, 0x53, 0x4f, - 0x55, 0x52, 0x43, 0x45, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x47, 0x49, 0x54, 0x48, 0x55, 0x42, - 0x5f, 0x55, 0x4e, 0x41, 0x55, 0x54, 0x48, 0x45, 0x4e, 0x54, 0x49, 0x43, 0x41, 0x54, 0x45, 0x44, - 0x5f, 0x4f, 0x52, 0x47, 0x10, 0x13, 0x12, 0x19, 0x0a, 0x15, 0x53, 0x4f, 0x55, 0x52, 0x43, 0x45, - 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x42, 0x55, 0x49, 0x4c, 0x44, 0x4b, 0x49, 0x54, 0x45, 0x10, - 0x14, 0x12, 0x16, 0x0a, 0x12, 0x53, 0x4f, 0x55, 0x52, 0x43, 0x45, 0x5f, 0x54, 0x59, 0x50, 0x45, - 0x5f, 0x47, 0x45, 0x52, 0x52, 0x49, 0x54, 0x10, 0x15, 0x12, 0x17, 0x0a, 0x13, 0x53, 0x4f, 0x55, - 0x52, 0x43, 0x45, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x4a, 0x45, 0x4e, 0x4b, 0x49, 0x4e, 0x53, - 0x10, 0x16, 0x12, 0x15, 0x0a, 0x11, 0x53, 0x4f, 0x55, 0x52, 0x43, 0x45, 0x5f, 0x54, 0x59, 0x50, - 0x45, 0x5f, 0x54, 0x45, 0x41, 0x4d, 0x53, 0x10, 0x17, 0x12, 0x21, 0x0a, 0x1d, 0x53, 0x4f, 0x55, - 0x52, 0x43, 0x45, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x4a, 0x46, 0x52, 0x4f, 0x47, 0x5f, 0x41, - 0x52, 0x54, 0x49, 0x46, 0x41, 0x43, 0x54, 0x4f, 0x52, 0x59, 0x10, 0x18, 0x12, 0x16, 0x0a, 0x12, - 0x53, 0x4f, 0x55, 0x52, 0x43, 0x45, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x53, 0x59, 0x53, 0x4c, - 0x4f, 0x47, 0x10, 0x19, 0x12, 0x27, 0x0a, 0x23, 0x53, 0x4f, 0x55, 0x52, 0x43, 0x45, 0x5f, 0x54, - 0x59, 0x50, 0x45, 0x5f, 0x50, 0x55, 0x42, 0x4c, 0x49, 0x43, 0x5f, 0x45, 0x56, 0x45, 0x4e, 0x54, - 0x5f, 0x4d, 0x4f, 0x4e, 0x49, 0x54, 0x4f, 0x52, 0x49, 0x4e, 0x47, 0x10, 0x1a, 0x12, 0x1e, 0x0a, - 0x1a, 0x53, 0x4f, 0x55, 0x52, 0x43, 0x45, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x53, 0x4c, 0x41, - 0x43, 0x4b, 0x5f, 0x52, 0x45, 0x41, 0x4c, 0x54, 0x49, 0x4d, 0x45, 0x10, 0x1b, 0x12, 0x1c, 0x0a, - 0x18, 0x53, 0x4f, 0x55, 0x52, 0x43, 0x45, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x47, 0x4f, 0x4f, - 0x47, 0x4c, 0x45, 0x5f, 0x44, 0x52, 0x49, 0x56, 0x45, 0x10, 0x1c, 0x12, 0x1a, 0x0a, 0x16, 0x53, - 0x4f, 0x55, 0x52, 0x43, 0x45, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x53, 0x48, 0x41, 0x52, 0x45, - 0x50, 0x4f, 0x49, 0x4e, 0x54, 0x10, 0x1d, 0x12, 0x1c, 0x0a, 0x18, 0x53, 0x4f, 0x55, 0x52, 0x43, - 0x45, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x47, 0x43, 0x53, 0x5f, 0x55, 0x4e, 0x41, 0x55, 0x54, - 0x48, 0x45, 0x44, 0x10, 0x1e, 0x12, 0x1b, 0x0a, 0x17, 0x53, 0x4f, 0x55, 0x52, 0x43, 0x45, 0x5f, - 0x54, 0x59, 0x50, 0x45, 0x5f, 0x41, 0x5a, 0x55, 0x52, 0x45, 0x5f, 0x52, 0x45, 0x50, 0x4f, 0x53, - 0x10, 0x1f, 0x42, 0x3b, 0x5a, 0x39, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, - 0x2f, 0x74, 0x72, 0x75, 0x66, 0x66, 0x6c, 0x65, 0x73, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, - 0x2f, 0x74, 0x72, 0x75, 0x66, 0x66, 0x6c, 0x65, 0x68, 0x6f, 0x67, 0x2f, 0x76, 0x33, 0x2f, 0x70, - 0x6b, 0x67, 0x2f, 0x70, 0x62, 0x2f, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x70, 0x62, 0x62, - 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x52, 0x45, 0x50, 0x4f, 0x53, 0x10, 0x1f, 0x42, 0x3b, 0x5a, 0x39, 0x67, 0x69, 0x74, 0x68, 0x75, + 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x74, 0x72, 0x75, 0x66, 0x66, 0x6c, 0x65, 0x73, 0x65, 0x63, + 0x75, 0x72, 0x69, 0x74, 0x79, 0x2f, 0x74, 0x72, 0x75, 0x66, 0x66, 0x6c, 0x65, 0x68, 0x6f, 0x67, + 0x2f, 0x76, 0x33, 0x2f, 0x70, 0x6b, 0x67, 0x2f, 0x70, 0x62, 0x2f, 0x73, 0x6f, 0x75, 0x72, 0x63, + 0x65, 0x73, 0x70, 0x62, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( diff --git a/pkg/pb/sourcespb/sources.pb.validate.go b/pkg/pb/sourcespb/sources.pb.validate.go index fcdc5ebbfbf4..91416c750ee4 100644 --- a/pkg/pb/sourcespb/sources.pb.validate.go +++ b/pkg/pb/sourcespb/sources.pb.validate.go @@ -121,6 +121,8 @@ func (m *LocalSource) validate(all bool) error { } } + // no validation rules for ScanPeriod + if len(errors) > 0 { return LocalSourceMultiError(errors) } diff --git a/pkg/sources/chunker_test.go b/pkg/sources/chunker_test.go index 0a782294b249..0a6711707156 100644 --- a/pkg/sources/chunker_test.go +++ b/pkg/sources/chunker_test.go @@ -7,7 +7,7 @@ import ( "testing" "testing/iotest" - diskbufferreader "github.com/bill-rich/disk-buffer-reader" + diskbufferreader "github.com/trufflesecurity/disk-buffer-reader" "github.com/stretchr/testify/assert" "github.com/trufflesecurity/trufflehog/v3/pkg/context" diff --git a/pkg/sources/filesystem/filesystem.go b/pkg/sources/filesystem/filesystem.go index 64eca62ce0cb..791f5eb93f60 100644 --- a/pkg/sources/filesystem/filesystem.go +++ b/pkg/sources/filesystem/filesystem.go @@ -7,7 +7,7 @@ import ( "os" "path/filepath" - diskbufferreader "github.com/bill-rich/disk-buffer-reader" + diskbufferreader "github.com/trufflesecurity/disk-buffer-reader" "github.com/go-errors/errors" "github.com/go-logr/logr" "google.golang.org/protobuf/proto" diff --git a/pkg/sources/gcs/gcs.go b/pkg/sources/gcs/gcs.go index 9531a8661788..202752085ddd 100644 --- a/pkg/sources/gcs/gcs.go +++ b/pkg/sources/gcs/gcs.go @@ -10,7 +10,7 @@ import ( "sync" "cloud.google.com/go/storage" - diskbufferreader "github.com/bill-rich/disk-buffer-reader" + diskbufferreader "github.com/trufflesecurity/disk-buffer-reader" "github.com/go-errors/errors" "github.com/go-logr/logr" "golang.org/x/oauth2" diff --git a/pkg/sources/git/git.go b/pkg/sources/git/git.go index 540c7b5be5e5..e0fbe5103d61 100644 --- a/pkg/sources/git/git.go +++ b/pkg/sources/git/git.go @@ -13,7 +13,7 @@ import ( "sync/atomic" "time" - diskbufferreader "github.com/bill-rich/disk-buffer-reader" + diskbufferreader "github.com/trufflesecurity/disk-buffer-reader" "github.com/go-errors/errors" "github.com/go-git/go-git/v5" "github.com/go-git/go-git/v5/plumbing" diff --git a/pkg/sources/job_progress_hook.go b/pkg/sources/job_progress_hook.go new file mode 100644 index 000000000000..5a592da3a0b3 --- /dev/null +++ b/pkg/sources/job_progress_hook.go @@ -0,0 +1,218 @@ +package sources + +import ( + "errors" + "fmt" + "strings" + "sync" + "time" + + lru "github.com/hashicorp/golang-lru/v2" + "github.com/trufflesecurity/trufflehog/v3/pkg/context" +) + +// UnitHook implements JobProgressHook for tracking the progress of each +// individual unit. +type UnitHook struct { + metrics *lru.Cache[string, *UnitMetrics] + mu sync.Mutex + NoopHook +} + +type UnitHookOpt func(*UnitHook) + +func WithUnitHookCache(cache *lru.Cache[string, *UnitMetrics]) UnitHookOpt { + return func(hook *UnitHook) { hook.metrics = cache } +} + +func NewUnitHook(ctx context.Context, opts ...UnitHookOpt) *UnitHook { + // lru.NewWithEvict can only fail if the size is < 0. + cache, _ := lru.NewWithEvict(1024, func(key string, value *UnitMetrics) { + if value.handled { + return + } + ctx.Logger().Error(fmt.Errorf("eviction"), "dropping unit metric", + "id", key, + "metric", value, + ) + }) + hook := UnitHook{metrics: cache} + for _, opt := range opts { + opt(&hook) + } + return &hook +} + +// id is a helper method to generate an ID for the given job and unit. +func (u *UnitHook) id(ref JobProgressRef, unit SourceUnit) string { + unitID := "" + if unit != nil { + unitID = unit.SourceUnitID() + } + return fmt.Sprintf("%d/%d/%s", ref.SourceID, ref.JobID, unitID) +} + +func (u *UnitHook) StartUnitChunking(ref JobProgressRef, unit SourceUnit, start time.Time) { + id := u.id(ref, unit) + u.mu.Lock() + defer u.mu.Unlock() + + u.metrics.Add(id, &UnitMetrics{ + Unit: unit, + Parent: ref, + StartTime: start, + }) +} + +func (u *UnitHook) EndUnitChunking(ref JobProgressRef, unit SourceUnit, end time.Time) { + id := u.id(ref, unit) + u.mu.Lock() + defer u.mu.Unlock() + + metrics, ok := u.metrics.Get(id) + if !ok { + return + } + metrics.EndTime = end +} + +func (u *UnitHook) ReportChunk(ref JobProgressRef, unit SourceUnit, chunk *Chunk) { + id := u.id(ref, unit) + u.mu.Lock() + defer u.mu.Unlock() + + metrics, ok := u.metrics.Get(id) + if !ok && unit != nil { + // The unit has been evicted. + return + } else if !ok && unit == nil { + // This is a chunk from a non-unit source. + metrics = &UnitMetrics{ + Unit: nil, + Parent: ref, + StartTime: ref.Snapshot().StartTime, + } + u.metrics.Add(id, metrics) + } + metrics.TotalChunks++ + metrics.TotalBytes += uint64(len(chunk.Data)) +} + +func (u *UnitHook) ReportError(ref JobProgressRef, err error) { + u.mu.Lock() + defer u.mu.Unlock() + + // Always add the error to the nil unit if it exists. + if metrics, ok := u.metrics.Get(u.id(ref, nil)); ok { + metrics.Errors = append(metrics.Errors, err) + } + + // Check if it's a ChunkError for a specific unit. + var chunkErr ChunkError + if !errors.As(err, &chunkErr) { + return + } + id := u.id(ref, chunkErr.Unit) + + metrics, ok := u.metrics.Get(id) + if !ok { + return + } + metrics.Errors = append(metrics.Errors, err) +} + +func (u *UnitHook) Finish(ref JobProgressRef) { + u.mu.Lock() + defer u.mu.Unlock() + // Clear out any metrics on this job. This covers the case for the + // source running without unit support. + prefix := u.id(ref, nil) + for _, id := range u.metrics.Keys() { + if !strings.HasPrefix(id, prefix) { + continue + } + metric, ok := u.metrics.Get(id) + if !ok { + continue + } + // If the unit is nil, the source does not support units. + // Use the overall job metrics instead. + if metric.Unit == nil { + snap := ref.Snapshot() + metric.StartTime = snap.StartTime + metric.EndTime = snap.EndTime + metric.Errors = snap.Errors + } + } +} + +// UnitMetrics gets all the currently active or newly finished metrics for this +// job. If a unit returned from this method has finished, it will be removed +// from the cache and no longer returned in successive calls to UnitMetrics(). +func (u *UnitHook) UnitMetrics() []UnitMetrics { + u.mu.Lock() + defer u.mu.Unlock() + output := make([]UnitMetrics, 0, u.metrics.Len()) + for _, id := range u.metrics.Keys() { + metric, ok := u.metrics.Get(id) + if !ok { + continue + } + output = append(output, *metric) + if metric.IsFinished() { + metric.handled = true + u.metrics.Remove(id) + } + } + return output +} + +type UnitMetrics struct { + Unit SourceUnit + Parent JobProgressRef + // Start and end time for chunking this unit. + StartTime time.Time + EndTime time.Time + // Total number of chunks produced from this unit. + TotalChunks uint64 + // Total number of bytes produced from this unit. + TotalBytes uint64 + // All errors encountered by this unit. + Errors []error + // Flag to mark that these metrics were intentionally evicted from + // the cache. + handled bool +} + +func (u UnitMetrics) IsFinished() bool { + return !u.EndTime.IsZero() +} + +// ElapsedTime is a convenience method that provides the elapsed time the job +// has been running. If it hasn't started yet, 0 is returned. If it has +// finished, the total time is returned. +func (u UnitMetrics) ElapsedTime() time.Duration { + if u.StartTime.IsZero() { + return 0 + } + if u.EndTime.IsZero() { + return time.Since(u.StartTime) + } + return u.EndTime.Sub(u.StartTime) +} + +// NoopHook implements JobProgressHook by doing nothing. This is useful for +// embedding in other structs to overwrite only the methods of the interface +// that you care about. +type NoopHook struct{} + +func (NoopHook) Start(JobProgressRef, time.Time) {} +func (NoopHook) End(JobProgressRef, time.Time) {} +func (NoopHook) StartEnumerating(JobProgressRef, time.Time) {} +func (NoopHook) EndEnumerating(JobProgressRef, time.Time) {} +func (NoopHook) StartUnitChunking(JobProgressRef, SourceUnit, time.Time) {} +func (NoopHook) EndUnitChunking(JobProgressRef, SourceUnit, time.Time) {} +func (NoopHook) ReportError(JobProgressRef, error) {} +func (NoopHook) ReportUnit(JobProgressRef, SourceUnit) {} +func (NoopHook) ReportChunk(JobProgressRef, SourceUnit, *Chunk) {} +func (NoopHook) Finish(JobProgressRef) {} diff --git a/pkg/sources/s3/s3.go b/pkg/sources/s3/s3.go index f27f54501699..e21830b7a5a1 100644 --- a/pkg/sources/s3/s3.go +++ b/pkg/sources/s3/s3.go @@ -14,7 +14,7 @@ import ( "github.com/aws/aws-sdk-go/service/s3" "github.com/aws/aws-sdk-go/service/s3/s3manager" "github.com/aws/aws-sdk-go/service/sts" - diskbufferreader "github.com/bill-rich/disk-buffer-reader" + diskbufferreader "github.com/trufflesecurity/disk-buffer-reader" "github.com/go-errors/errors" "github.com/go-logr/logr" "golang.org/x/sync/errgroup" diff --git a/pkg/sources/source_manager_test.go b/pkg/sources/source_manager_test.go index e6bde739d3af..2c8d66cf3a72 100644 --- a/pkg/sources/source_manager_test.go +++ b/pkg/sources/source_manager_test.go @@ -3,8 +3,10 @@ package sources import ( "errors" "fmt" + "sort" "testing" + lru "github.com/hashicorp/golang-lru/v2" "github.com/stretchr/testify/assert" "google.golang.org/protobuf/types/known/anypb" @@ -200,6 +202,8 @@ func (c *unitChunker) ChunkUnit(ctx context.Context, unit SourceUnit, rep ChunkR if err := rep.ChunkErr(ctx, fmt.Errorf(step.err)); err != nil { return err } + } + if step.output == "" { continue } if err := rep.ChunkOk(ctx, Chunk{Data: []byte(step.output)}); err != nil { @@ -310,3 +314,114 @@ func TestSourceManagerAvailableCapacity(t *testing.T) { <-ref.Done() // Wait for the job to finish. assert.Equal(t, 1337, mgr.AvailableCapacity()) } + +func TestSourceManagerUnitHook(t *testing.T) { + hook := NewUnitHook(context.TODO()) + + input := []unitChunk{ + {unit: "one", output: "bar"}, + {unit: "two", err: "oh no"}, + {unit: "three", err: "not again"}, + } + mgr := NewManager( + WithBufferedOutput(8), + WithSourceUnits(), WithConcurrentUnits(1), + WithReportHook(hook), + ) + source, err := buildDummy(&unitChunker{input}) + assert.NoError(t, err) + ref, err := mgr.Run(context.Background(), "dummy", source) + assert.NoError(t, err) + <-ref.Done() + + metrics := hook.UnitMetrics() + assert.Equal(t, 3, len(metrics)) + sort.Slice(metrics, func(i, j int) bool { + return metrics[i].EndTime.Before(metrics[j].EndTime) + }) + m0, m1, m2 := metrics[0], metrics[1], metrics[2] + + assert.Equal(t, "one", m0.Unit.SourceUnitID()) + assert.Equal(t, uint64(1), m0.TotalChunks) + assert.Equal(t, uint64(3), m0.TotalBytes) + assert.NotZero(t, m0.StartTime) + assert.NotZero(t, m0.EndTime) + assert.NotZero(t, m0.ElapsedTime()) + assert.Equal(t, 0, len(m0.Errors)) + + assert.Equal(t, "two", m1.Unit.SourceUnitID()) + assert.Equal(t, uint64(0), m1.TotalChunks) + assert.Equal(t, uint64(0), m1.TotalBytes) + assert.NotZero(t, m1.StartTime) + assert.NotZero(t, m1.EndTime) + assert.NotZero(t, m1.ElapsedTime()) + assert.Equal(t, 1, len(m1.Errors)) + + assert.Equal(t, "three", m2.Unit.SourceUnitID()) + assert.Equal(t, uint64(0), m2.TotalChunks) + assert.Equal(t, uint64(0), m2.TotalBytes) + assert.NotZero(t, m2.StartTime) + assert.NotZero(t, m2.EndTime) + assert.NotZero(t, m2.ElapsedTime()) + assert.Equal(t, 1, len(m2.Errors)) +} + +// TestSourceManagerUnitHookNoBlock tests that the UnitHook drops metrics if +// they aren't handled fast enough. +func TestSourceManagerUnitHookNoBlock(t *testing.T) { + var evictedKeys []string + cache, _ := lru.NewWithEvict(1, func(key string, _ *UnitMetrics) { + evictedKeys = append(evictedKeys, key) + }) + hook := NewUnitHook(context.TODO(), WithUnitHookCache(cache)) + + input := []unitChunk{ + {unit: "one", output: "bar"}, + {unit: "two", err: "oh no"}, + {unit: "three", err: "not again"}, + } + mgr := NewManager( + WithBufferedOutput(8), + WithSourceUnits(), WithConcurrentUnits(1), + WithReportHook(hook), + ) + source, err := buildDummy(&unitChunker{input}) + assert.NoError(t, err) + ref, err := mgr.Run(context.Background(), "dummy", source) + assert.NoError(t, err) + <-ref.Done() + + assert.Equal(t, 2, len(evictedKeys)) + metrics := hook.UnitMetrics() + assert.Equal(t, 1, len(metrics)) + assert.Equal(t, "three", metrics[0].Unit.SourceUnitID()) +} + +// TestSourceManagerUnitHookNoUnits tests whether the UnitHook works for +// sources that don't support units. +func TestSourceManagerUnitHookNoUnits(t *testing.T) { + hook := NewUnitHook(context.TODO()) + + mgr := NewManager( + WithBufferedOutput(8), + WithReportHook(hook), + ) + source, err := buildDummy(&counterChunker{count: 5}) + assert.NoError(t, err) + + ref, err := mgr.Run(context.Background(), "dummy", source) + assert.NoError(t, err) + <-ref.Done() + + metrics := hook.UnitMetrics() + assert.Equal(t, 1, len(metrics)) + + m := metrics[0] + assert.Equal(t, nil, m.Unit) + assert.Equal(t, uint64(5), m.TotalChunks) + assert.Equal(t, uint64(5), m.TotalBytes) + assert.NotZero(t, m.StartTime) + assert.NotZero(t, m.EndTime) + assert.NotZero(t, m.ElapsedTime()) + assert.Equal(t, 0, len(m.Errors)) +} diff --git a/proto/detectors.proto b/proto/detectors.proto index f1f4bb86d171..13376e99e94a 100644 --- a/proto/detectors.proto +++ b/proto/detectors.proto @@ -361,7 +361,7 @@ enum DetectorType { Imagga = 349; SMSApi = 350; Distribusion = 351; - Blablabus = 352; + Blablabus = 352 [deprecated = true]; WordsApi = 353; Currencylayer = 354; Html2Pdf = 355; @@ -588,7 +588,7 @@ enum DetectorType { Qubole = 577; CarbonInterface = 578; Intrinio = 579; - QuickMetrics = 580; + QuickMetrics = 580 [deprecated = true]; ScrapeStack = 581; TechnicalAnalysisApi = 582; Urlscan = 583; @@ -628,7 +628,7 @@ enum DetectorType { Nylas = 617; Squareup = 618; Dandelion = 619; - DataFire = 620; + DataFire = 620 [deprecated = true]; DeepAI = 621; MeaningCloud = 622; NeutrinoApi = 623; @@ -642,7 +642,7 @@ enum DetectorType { TheOddsApi = 631; Apacta = 632; GetSandbox = 633; - Happi = 634; + Happi = 634 [deprecated = true]; Oanda = 635; FastForex = 636; APIMatic = 637; @@ -780,7 +780,7 @@ enum DetectorType { ConversionTools = 769; CraftMyPDF = 770; ExportSDK = 771; - GlitterlyAPI = 772; + GlitterlyAPI = 772 [deprecated = true]; Hybiscus = 773; Miro = 774; Statuspage = 775; @@ -815,7 +815,7 @@ enum DetectorType { PackageCloud = 804; Cloudsmith = 805; Flowdash = 806; - Flowdock = 807; + Flowdock = 807 [deprecated = true]; Fibery = 808; Typetalk = 809; VoodooSMS = 810; @@ -947,6 +947,14 @@ enum DetectorType { SourcegraphCody = 936; Voiceflow = 937; Privacy = 938; + IPInfo = 939; + Ip2location = 940; + Instamojo = 941; + Portainer = 942; + PortainerToken = 943; + Loggly = 944; + OpenVpn = 945; + VagrantCloudPersonalToken = 946; } message Result { diff --git a/proto/sources.proto b/proto/sources.proto index 61c1d29f7ff0..50fbcf935dfc 100644 --- a/proto/sources.proto +++ b/proto/sources.proto @@ -49,9 +49,16 @@ enum SourceType { message LocalSource { string type = 1 ; string name = 2 ; - google.protobuf.Duration scan_interval = 3; + // DEPRECATED: scan_interval is deprecated and can be removed when we no longer depend on the name. + // Deprecating in favor of scan_period due to the fact that scan_interval is a duration + // which is a fixed-length span of time represented as a count of seconds and fractions of seconds + // at nanosecond resolution. Most of the time, we want to be able to specify a scan interval in + // human-readable format (e.g. 45s, 30m, 12h, etc.) which is not possible with a duration. + // https://protobuf.dev/reference/protobuf/google.protobuf/#duration + google.protobuf.Duration scan_interval = 3 [deprecated = true]; bool verify = 4; google.protobuf.Any connection = 5; + string scan_period = 6; } message AzureStorage {