diff --git a/.github/workflows/coverage.yml b/.github/workflows/coverage.yml
index 074bbd20a..b6b50327c 100644
--- a/.github/workflows/coverage.yml
+++ b/.github/workflows/coverage.yml
@@ -23,7 +23,7 @@ jobs:
- name: Set up Go
uses: actions/setup-go@4a3601121dd01d1626a1e23e37211e3254c1c06c # v6.4.0
with:
- go-version: '1.25.7'
+ go-version: '1.26.8'
- name: tests
run: make test
diff --git a/.github/workflows/nightly.yaml b/.github/workflows/nightly.yaml
index f84f4c389..2ce6a0111 100644
--- a/.github/workflows/nightly.yaml
+++ b/.github/workflows/nightly.yaml
@@ -23,7 +23,7 @@ jobs:
- name: Set up Go
uses: actions/setup-go@4a3601121dd01d1626a1e23e37211e3254c1c06c # v6.4.0
with:
- go-version: ~1.25.7
+ go-version: ~1.26.8
- name: Log in to GHCR
uses: docker/login-action@b45d80f862d83dbcd57f89517bcf500b2ab88fb2 # v4.0.0
with:
diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
index 468743e63..cdce57ece 100644
--- a/.github/workflows/release.yml
+++ b/.github/workflows/release.yml
@@ -23,7 +23,7 @@ jobs:
- name: Set up Go
uses: actions/setup-go@4a3601121dd01d1626a1e23e37211e3254c1c06c # v6.4.0
with:
- go-version: ~1.25.7
+ go-version: ~1.26.8
- name: Log in to GHCR
uses: docker/login-action@b45d80f862d83dbcd57f89517bcf500b2ab88fb2 # v4.0.0
with:
diff --git a/buf.gen.yaml b/buf.gen.yaml
old mode 100755
new mode 100644
index d9886d9a1..87ae00821
--- a/buf.gen.yaml
+++ b/buf.gen.yaml
@@ -1,40 +1,52 @@
-#!/usr/bin/env -S buf generate --template
----
-version: v1
+version: v2
+inputs:
+ - directory: proto
managed:
enabled: true
- go_package_prefix:
- default: github.com/Permify/permify/pkg/pb
- except:
- - buf.build/googleapis/googleapis
- - buf.build/envoyproxy/protoc-gen-validate
- - buf.build/grpc-ecosystem/grpc-gateway
+ disable:
+ - file_option: go_package
+ module: buf.build/googleapis/googleapis
+ - file_option: go_package
+ module: buf.build/grpc-ecosystem/grpc-gateway
+ - file_option: go_package
+ module: buf.build/bufbuild/protovalidate
+ override:
+ - file_option: go_package_prefix
+ value: github.com/Permify/permify/pkg/pb
plugins:
- - name: go
- path: ["go", "run", "google.golang.org/protobuf/cmd/protoc-gen-go"]
+ - local:
+ - go
+ - run
+ - google.golang.org/protobuf/cmd/protoc-gen-go
out: pkg/pb
opt: paths=source_relative
- - name: go-grpc
- path: ["go", "run", "google.golang.org/grpc/cmd/protoc-gen-go-grpc"]
+ - local:
+ - go
+ - run
+ - google.golang.org/grpc/cmd/protoc-gen-go-grpc
out: pkg/pb
opt: paths=source_relative
- - name: go-vtproto
- path: ["go", "run", "github.com/planetscale/vtprotobuf/cmd/protoc-gen-go-vtproto"]
+ - local:
+ - go
+ - run
+ - github.com/planetscale/vtprotobuf/cmd/protoc-gen-go-vtproto
out: pkg/pb
opt: paths=source_relative,features=marshal+unmarshal+size+clone+pool+equal
- - name: validate
- path: ["go", "run", "github.com/envoyproxy/protoc-gen-validate"]
- out: pkg/pb
- opt: paths=source_relative,lang=go
- - name: grpc-gateway
- path: ["go", "run", "github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-grpc-gateway"]
+ - local:
+ - go
+ - run
+ - github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-grpc-gateway
out: pkg/pb
opt: paths=source_relative
- - name: openapiv2
- path: ["go", "run", "github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-openapiv2"]
+ - local:
+ - go
+ - run
+ - github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-openapiv2
out: docs/api-reference
opt: openapi_naming_strategy=simple,allow_merge=true
- - name: openapiv2
- path: ["go", "run", "github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-openapiv2"]
+ - local:
+ - go
+ - run
+ - github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-openapiv2
out: docs/api-reference/openapiv2
- opt: omit_enum_default_value=true,openapi_naming_strategy=simple,allow_merge=true
+ opt: omit_enum_default_value=true,openapi_naming_strategy=simple,allow_merge=true
\ No newline at end of file
diff --git a/buf.work.yaml b/buf.work.yaml
deleted file mode 100644
index 2b96194a4..000000000
--- a/buf.work.yaml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-version: v1
-directories:
- - proto
\ No newline at end of file
diff --git a/go.mod b/go.mod
index 24e2074fa..6f28cfef1 100644
--- a/go.mod
+++ b/go.mod
@@ -1,10 +1,9 @@
module github.com/Permify/permify
-go 1.25.7
+go 1.26.0
tool (
github.com/bufbuild/buf/cmd/buf
- github.com/envoyproxy/protoc-gen-validate
github.com/golangci/golangci-lint/v2/cmd/golangci-lint
github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-grpc-gateway
github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-openapiv2
@@ -23,7 +22,6 @@ require (
github.com/cespare/xxhash/v2 v2.3.0
github.com/dgraph-io/ristretto v1.0.0
github.com/dustin/go-humanize v1.0.1
- github.com/envoyproxy/protoc-gen-validate v1.3.3
github.com/exaring/otelpgx v0.10.0
github.com/fatih/color v1.19.0
github.com/go-jose/go-jose/v3 v3.0.5
@@ -70,12 +68,12 @@ require (
go.opentelemetry.io/otel/sdk v1.46.0
go.opentelemetry.io/otel/sdk/metric v1.46.0
go.opentelemetry.io/otel/trace v1.46.0
- golang.org/x/exp v0.0.0-20251002181428-27f1f14c8bb9
+ golang.org/x/exp v0.0.0-20260820142414-ca536658362e
golang.org/x/net v0.58.0 // indirect
golang.org/x/sync v0.22.0
- google.golang.org/genproto/googleapis/api v0.0.0-20260526163538-3dc84a4a5aaa
+ google.golang.org/genproto/googleapis/api v0.0.0-20260819154853-08b0e4226688
google.golang.org/grpc v1.83.2
- google.golang.org/protobuf v1.36.11
+ google.golang.org/protobuf v1.36.12
resenje.org/singleflight v0.4.3
)
@@ -84,18 +82,18 @@ require (
4d63.com/gocheckcompilerdirectives v1.3.0 // indirect
4d63.com/gochecknoglobals v0.2.2 // indirect
buf.build/gen/go/bufbuild/bufplugin/protocolbuffers/go v1.36.10-20250718181942-e35f9b667443.1 // indirect
- buf.build/gen/go/bufbuild/protovalidate/protocolbuffers/go v1.36.10-20250717185734-6c6e0d3c608e.1 // indirect
+ buf.build/gen/go/bufbuild/protovalidate/protocolbuffers/go v1.36.12-20260825204119-511051f7f437.1
buf.build/gen/go/bufbuild/registry/connectrpc/go v1.19.0-20250924144421-cb55f06efbd2.1 // indirect
buf.build/gen/go/bufbuild/registry/protocolbuffers/go v1.36.10-20250924144421-cb55f06efbd2.1 // indirect
buf.build/gen/go/pluginrpc/pluginrpc/protocolbuffers/go v1.36.9-20241007202033-cf42259fcbfc.1 // indirect
buf.build/go/app v0.1.0 // indirect
buf.build/go/bufplugin v0.9.0 // indirect
buf.build/go/interrupt v1.1.0 // indirect
- buf.build/go/protovalidate v1.0.0 // indirect
+ buf.build/go/protovalidate v1.4.0
buf.build/go/protoyaml v0.6.0 // indirect
buf.build/go/spdx v0.2.0 // indirect
buf.build/go/standard v0.1.0 // indirect
- cel.dev/expr v0.25.2 // indirect
+ cel.dev/expr v0.25.3 // indirect
cloud.google.com/go v0.123.0 // indirect
cloud.google.com/go/ai v0.12.1 // indirect
cloud.google.com/go/auth v0.18.2 // indirect
@@ -217,7 +215,6 @@ require (
github.com/hashicorp/go-version v1.7.0 // indirect
github.com/hashicorp/golang-lru/v2 v2.0.7 // indirect
github.com/hexops/gotextdiff v1.0.3 // indirect
- github.com/iancoleman/strcase v0.3.0 // indirect
github.com/jdx/go-netrc v1.0.0 // indirect
github.com/jgautheron/goconst v1.8.2 // indirect
github.com/jingyugao/rowserrcheck v1.1.1 // indirect
@@ -242,7 +239,6 @@ require (
github.com/lestrrat-go/iter v1.0.2 // indirect
github.com/lestrrat-go/option v1.0.1 // indirect
github.com/lucasb-eyer/go-colorful v1.2.0 // indirect
- github.com/lyft/protoc-gen-star/v2 v2.0.4 // indirect
github.com/macabu/inamedparam v0.2.0 // indirect
github.com/manuelarte/embeddedstructfieldcheck v0.4.0 // indirect
github.com/manuelarte/funcorder v0.5.0 // indirect
@@ -326,7 +322,7 @@ require (
go.uber.org/zap v1.27.0 // indirect
go.yaml.in/yaml/v3 v3.0.5
golang.org/x/exp/typeparams v0.0.0-20250911091902-df9299821621 // indirect
- golang.org/x/mod v0.38.0 // indirect
+ golang.org/x/mod v0.39.0 // indirect
golang.org/x/oauth2 v0.36.0 // indirect
golang.org/x/term v0.45.0 // indirect
golang.org/x/time v0.14.0 // indirect
@@ -409,11 +405,12 @@ require (
golang.org/x/crypto v0.55.0 // indirect
golang.org/x/sys v0.47.0 // indirect
golang.org/x/text v0.41.0 // indirect
- golang.org/x/tools v0.48.0 // indirect
- google.golang.org/genproto/googleapis/rpc v0.0.0-20260526163538-3dc84a4a5aaa // indirect
+ golang.org/x/tools v0.49.0 // indirect
+ google.golang.org/genproto/googleapis/rpc v0.0.0-20260819154853-08b0e4226688 // indirect
)
require (
+ cel.dev/cel-go v0.32.0 // indirect
github.com/clipperhouse/displaywidth v0.10.0 // indirect
github.com/clipperhouse/uax29/v2 v2.6.0 // indirect
github.com/moby/moby/api v1.54.1 // indirect
diff --git a/go.sum b/go.sum
index dcf8a95f1..a43e8165c 100644
--- a/go.sum
+++ b/go.sum
@@ -4,8 +4,8 @@
4d63.com/gochecknoglobals v0.2.2/go.mod h1:lLxwTQjL5eIesRbvnzIP3jZtG140FnTdz+AlMa+ogt0=
buf.build/gen/go/bufbuild/bufplugin/protocolbuffers/go v1.36.10-20250718181942-e35f9b667443.1 h1:FzJGrb8r7vir+P3zJ5Ebey8p54LYTYtQsrM/U35YO9Q=
buf.build/gen/go/bufbuild/bufplugin/protocolbuffers/go v1.36.10-20250718181942-e35f9b667443.1/go.mod h1:E6HwqUm4Ag7bXtg/tX7jHWO7CgpknbmeACgDax0icV0=
-buf.build/gen/go/bufbuild/protovalidate/protocolbuffers/go v1.36.10-20250717185734-6c6e0d3c608e.1 h1:N4XvWMoswHV6F6c8vmWw2BeR9hYuUX0wrr0NssttyUw=
-buf.build/gen/go/bufbuild/protovalidate/protocolbuffers/go v1.36.10-20250717185734-6c6e0d3c608e.1/go.mod h1:fUl8CEN/6ZAMk6bP8ahBJPUJw7rbp+j4x+wCcYi2IG4=
+buf.build/gen/go/bufbuild/protovalidate/protocolbuffers/go v1.36.12-20260825204119-511051f7f437.1 h1:Slv0uGxx219srASyiaI5C9cDlyG8kNDcXpTSYcuAeE4=
+buf.build/gen/go/bufbuild/protovalidate/protocolbuffers/go v1.36.12-20260825204119-511051f7f437.1/go.mod h1:TCt1lluMFnctISJXvkIQ4x3ABrPuUKCWKyjKdkJNBpw=
buf.build/gen/go/bufbuild/registry/connectrpc/go v1.19.0-20250924144421-cb55f06efbd2.1 h1:GPNjspvq4O2Cj1BJ5Z4c7Y+I9pDX5ixlbcGoqxyBDx0=
buf.build/gen/go/bufbuild/registry/connectrpc/go v1.19.0-20250924144421-cb55f06efbd2.1/go.mod h1:V7mUsvSd9Gw0ir8u7Jgh+IpSm631EqcdMEj29un7YOY=
buf.build/gen/go/bufbuild/registry/protocolbuffers/go v1.36.10-20250924144421-cb55f06efbd2.1 h1:4ZcqdlWZF5tQUyHBeLyOwFjRwZ/93X/W5GfOZX9dJZo=
@@ -18,16 +18,18 @@ buf.build/go/bufplugin v0.9.0 h1:ktZJNP3If7ldcWVqh46XKeiYJVPxHQxCfjzVQDzZ/lo=
buf.build/go/bufplugin v0.9.0/go.mod h1:Z0CxA3sKQ6EPz/Os4kJJneeRO6CjPeidtP1ABh5jPPY=
buf.build/go/interrupt v1.1.0 h1:olBuhgv9Sav4/9pkSLoxgiOsZDgM5VhRhvRpn3DL0lE=
buf.build/go/interrupt v1.1.0/go.mod h1:ql56nXPG1oHlvZa6efNC7SKAQ/tUjS6z0mhJl0gyeRM=
-buf.build/go/protovalidate v1.0.0 h1:IAG1etULddAy93fiBsFVhpj7es5zL53AfB/79CVGtyY=
-buf.build/go/protovalidate v1.0.0/go.mod h1:KQmEUrcQuC99hAw+juzOEAmILScQiKBP1Oc36vvCLW8=
+buf.build/go/protovalidate v1.4.0 h1:UjLrYbt5VX7+TMOs2+pG5FhZhIG1mSfK4EIopbb4LcM=
+buf.build/go/protovalidate v1.4.0/go.mod h1:8vJfzNT6NIG2qm3uFsJDXMlRmG+bQJzbcIn1Aa0vPGs=
buf.build/go/protoyaml v0.6.0 h1:Nzz1lvcXF8YgNZXk+voPPwdU8FjDPTUV4ndNTXN0n2w=
buf.build/go/protoyaml v0.6.0/go.mod h1:RgUOsBu/GYKLDSIRgQXniXbNgFlGEZnQpRAUdLAFV2Q=
buf.build/go/spdx v0.2.0 h1:IItqM0/cMxvFJJumcBuP8NrsIzMs/UYjp/6WSpq8LTw=
buf.build/go/spdx v0.2.0/go.mod h1:bXdwQFem9Si3nsbNy8aJKGPoaPi5DKwdeEp5/ArZ6w8=
buf.build/go/standard v0.1.0 h1:g98T9IyvAl0vS3Pq8iVk6Cvj2ZiFvoUJRtfyGa0120U=
buf.build/go/standard v0.1.0/go.mod h1:PiqpHz/7ZFq+kqvYhc/SK3lxFIB9N/aiH2CFC2JHIQg=
-cel.dev/expr v0.25.2 h1:K6j46C81hXtZQfuX60cVWQFBJahKSE2gfRbNuvr5bFs=
-cel.dev/expr v0.25.2/go.mod h1:hrXvqGP6G6gyx8UAHSHJ5RGk//1Oj5nXQ2NI02Nrsg4=
+cel.dev/cel-go v0.32.0 h1:irvpFKr5EuGPyxeME03ERh0rii1TX+BDAnB9eL3IvNk=
+cel.dev/cel-go v0.32.0/go.mod h1:DnVip7tpJSsgZymwfT+m1tnEVy3ivAjSMXPx12YrMkU=
+cel.dev/expr v0.25.3 h1:A2jO8jwOugrrovveCWfj0KEZOfqiLgAcwjpHPhzIGw0=
+cel.dev/expr v0.25.3/go.mod h1:hrXvqGP6G6gyx8UAHSHJ5RGk//1Oj5nXQ2NI02Nrsg4=
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
cloud.google.com/go v0.123.0 h1:2NAUJwPR47q+E35uaJeYoNhuNEM9kM8SjgRgdeOJUSE=
cloud.google.com/go v0.123.0/go.mod h1:xBoMV08QcqUGuPW65Qfm1o9Y4zKZBpGS+7bImXLTAZU=
@@ -150,6 +152,8 @@ github.com/breml/bidichk v0.3.3 h1:WSM67ztRusf1sMoqH6/c4OBCUlRVTKq+CbSeo0R17sE=
github.com/breml/bidichk v0.3.3/go.mod h1:ISbsut8OnjB367j5NseXEGGgO/th206dVa427kR8YTE=
github.com/breml/errchkjson v0.4.1 h1:keFSS8D7A2T0haP9kzZTi7o26r7kE3vymjZNeNDRDwg=
github.com/breml/errchkjson v0.4.1/go.mod h1:a23OvR6Qvcl7DG/Z4o0el6BRAjKnaReoPQFciAl9U3s=
+github.com/brianvoe/gofakeit/v6 v6.28.0 h1:Xib46XXuQfmlLS2EXRuJpqcw8St6qSZz75OUo0tgAW4=
+github.com/brianvoe/gofakeit/v6 v6.28.0/go.mod h1:Xj58BMSnFqcn/fAQeSK+/PLtC5kSb7FJIq4JyGa8vEs=
github.com/bufbuild/buf v1.58.0 h1:TMgp0jmfPD5SixbUCB2iqGnK/X+2KQXTzsVc7F2LbLc=
github.com/bufbuild/buf v1.58.0/go.mod h1:guevy4hwwKlc9h69k4E9O/D23ecJHnP5LJ9QlDQoBtg=
github.com/bufbuild/protocompile v0.14.1 h1:iA73zAf/fyljNjQKwYzUHD6AD4R8KMasmwa/FBatYVw=
@@ -456,8 +460,6 @@ github.com/hashicorp/golang-lru/v2 v2.0.7 h1:a+bsQ5rvGLjzHuww6tVxozPZFVghXaHOwFs
github.com/hashicorp/golang-lru/v2 v2.0.7/go.mod h1:QeFd9opnmA6QUJc5vARoKUSoFhyfM2/ZepoAG6RGpeM=
github.com/hexops/gotextdiff v1.0.3 h1:gitA9+qJrrTCsiCl7+kh75nPqQt1cx4ZkudSTLoUqJM=
github.com/hexops/gotextdiff v1.0.3/go.mod h1:pSWU5MAI3yDq+fZBTazCSJysOMbxWL1BSow5/V2vxeg=
-github.com/iancoleman/strcase v0.3.0 h1:nTXanmYxhfFAMjZL34Ov6gkzEsSJZ5DbhxWjvSASxEI=
-github.com/iancoleman/strcase v0.3.0/go.mod h1:iwCmte+B7n89clKwxIoIXy/HfoL7AsD47ZCWhYzw7ho=
github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
github.com/jackc/chunkreader v1.0.0 h1:4s39bBR8ByfqH+DKm8rQA3E1LHZWB9XWcrz8fqaZbe0=
@@ -600,8 +602,6 @@ github.com/lucasb-eyer/go-colorful v1.2.0 h1:1nnpGOrhyZZuNyfu1QjKiUICQ74+3FNCN69
github.com/lucasb-eyer/go-colorful v1.2.0/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0=
github.com/lufia/plan9stats v0.0.0-20251013123823-9fd1530e3ec3 h1:PwQumkgq4/acIiZhtifTV5OUqqiP82UAl0h87xj/l9k=
github.com/lufia/plan9stats v0.0.0-20251013123823-9fd1530e3ec3/go.mod h1:autxFIvghDt3jPTLoqZ9OZ7s9qTGNAWmYCjVFWPX/zg=
-github.com/lyft/protoc-gen-star/v2 v2.0.4 h1:JDlNKttNIRd68AAIychs0AqEpO8/I/WYi01OQ7Raw6Q=
-github.com/lyft/protoc-gen-star/v2 v2.0.4/go.mod h1:amey7yeodaJhXSbf/TlLvWiqQfLOSpEk//mLlc+axEk=
github.com/macabu/inamedparam v0.2.0 h1:VyPYpOc10nkhI2qeNUdh3Zket4fcZjEWe35poddBCpE=
github.com/macabu/inamedparam v0.2.0/go.mod h1:+Pee9/YfGe5LJ62pYXqB89lJ+0k5bsR8Wgz/C0Zlq3U=
github.com/magiconair/properties v1.8.10 h1:s31yESBquKXCV9a/ScB3ESkOjUYYv+X0rg8SYxI99mE=
@@ -750,6 +750,8 @@ github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec h1:W09IVJc94
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo=
github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ=
github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88=
+github.com/rodaine/protogofakeit v0.1.1 h1:ZKouljuRM3A+TArppfBqnH8tGZHOwM/pjvtXe9DaXH8=
+github.com/rodaine/protogofakeit v0.1.1/go.mod h1:pXn/AstBYMaSfc1/RqH3N82pBuxtWgejz1AlYpY1mI0=
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
github.com/rogpeppe/go-internal v1.14.1 h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0tI/otEQ=
github.com/rogpeppe/go-internal v1.14.1/go.mod h1:MaRKkUm5W0goXpeCfT7UZI6fk/L7L7so1lCWt35ZSgc=
@@ -1016,8 +1018,8 @@ golang.org/x/crypto v0.20.0/go.mod h1:Xwo95rrVNIoSMx9wa1JroENMToLWn3RNVrTBpLHgZP
golang.org/x/crypto v0.55.0 h1:+KWHjbgOaAQ66dh/YlkZKHlz9ZUlq61AFirAR9ntP8M=
golang.org/x/crypto v0.55.0/go.mod h1:uq0V9dE/fzQuJtbnL+2EhWOE63vo164FY8xqEnV9xis=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
-golang.org/x/exp v0.0.0-20251002181428-27f1f14c8bb9 h1:TQwNpfvNkxAVlItJf6Cr5JTsVZoC/Sj7K3OZv2Pc14A=
-golang.org/x/exp v0.0.0-20251002181428-27f1f14c8bb9/go.mod h1:TwQYMMnGpvZyc+JpB/UAuTNIsVJifOlSkrZkhcvpVUk=
+golang.org/x/exp v0.0.0-20260820142414-ca536658362e h1:01Ju2A/fZKkci4zqx0eZxw//DnRYOnBiGJG14hFBhO8=
+golang.org/x/exp v0.0.0-20260820142414-ca536658362e/go.mod h1:zeBbvyFKDaLwa7CH/zI8KXt7gTl14SF7sO08Pl5jBCM=
golang.org/x/exp/typeparams v0.0.0-20220428152302-39d4317da171/go.mod h1:AbB0pIl9nAr9wVwH+Z2ZpaocVmF5I4GyWCDIsVjR0bk=
golang.org/x/exp/typeparams v0.0.0-20230203172020-98cc5a0785f9/go.mod h1:AbB0pIl9nAr9wVwH+Z2ZpaocVmF5I4GyWCDIsVjR0bk=
golang.org/x/exp/typeparams v0.0.0-20250911091902-df9299821621 h1:Yl4H5w2RV7L/dvSHp2GerziT5K2CORgFINPaMFxWGWw=
@@ -1037,8 +1039,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/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
golang.org/x/mod v0.13.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
-golang.org/x/mod v0.38.0 h1:MECBjubtXD7yj4HrhIUcywNaGeNVUdfVnxmPajOk4yk=
-golang.org/x/mod v0.38.0/go.mod h1:V6Xz0pq8TQ3dGqVQ1FVHuelZpAL0uNhSkk9ogYP3c40=
+golang.org/x/mod v0.39.0 h1:UF5zwQdCRRUpHfyPwr7d4UrGiVeldIsogtzWVnczL74=
+golang.org/x/mod v0.39.0/go.mod h1:bvIbwjQ0HUFFf5AKukeeYQG4ZBUG9yxQbR9aEweIwYY=
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-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
@@ -1161,8 +1163,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.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58=
golang.org/x/tools v0.14.0/go.mod h1:uYBEerGOWcJyEORxN+Ek8+TT266gXkNlHdJBwexUsBg=
-golang.org/x/tools v0.48.0 h1:3+hClM1aLL5mjMKm5ovokw9epgRXPuu2tILgismM6RE=
-golang.org/x/tools v0.48.0/go.mod h1:08xX0orndb/F7jJxGDicx061tyd5pcMto75YMAXr6lk=
+golang.org/x/tools v0.49.0 h1:3NI7VXzL9+1WZD52Dx2ttoPwD5DWrFGpl9mFZDlmisI=
+golang.org/x/tools v0.49.0/go.mod h1:SJNXV9DBKT0UbdttsQjbfJlAE/q+y36++zo3uL3N0Oo=
golang.org/x/tools/go/expect v0.1.1-deprecated h1:jpBZDwmgPhXsKZC6WhL20P4b/wmnpsEAGHaNy0n/rJM=
golang.org/x/tools/go/expect v0.1.1-deprecated/go.mod h1:eihoPOH+FgIqa3FpoTwguz/bVUSGBlGQU67vpBeOrBY=
golang.org/x/tools/go/packages/packagestest v0.1.1-deprecated h1:1h2MnaIAIXISqTFKdENegdpAgUXz6NrPEsbIeWaBRvM=
@@ -1184,10 +1186,10 @@ google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98
google.golang.org/genproto v0.0.0-20200423170343-7949de9c1215/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto v0.0.0-20260128011058-8636f8732409 h1:VQZ/yAbAtjkHgH80teYd2em3xtIkkHd7ZhqfH2N9CsM=
google.golang.org/genproto v0.0.0-20260128011058-8636f8732409/go.mod h1:rxKD3IEILWEu3P44seeNOAwZN4SaoKaQ/2eTg4mM6EM=
-google.golang.org/genproto/googleapis/api v0.0.0-20260526163538-3dc84a4a5aaa h1:Kjn0N0tCrDgiAFW+lGO4JZ3ck44CehvJQMAwj9QF0G8=
-google.golang.org/genproto/googleapis/api v0.0.0-20260526163538-3dc84a4a5aaa/go.mod h1:q4lMZS6kskjT5HvCPrnnypcDPVJqT/f4nfxmkE7gryY=
-google.golang.org/genproto/googleapis/rpc v0.0.0-20260526163538-3dc84a4a5aaa h1:mZHHdPZl0dbGHCflZgAq/Q468DWVFcU2whhB2KAo8fk=
-google.golang.org/genproto/googleapis/rpc v0.0.0-20260526163538-3dc84a4a5aaa/go.mod h1:4Hqkh8ycfw05ld/3BWL7rJOSfebL2Q+DVDeRgYgxUU8=
+google.golang.org/genproto/googleapis/api v0.0.0-20260819154853-08b0e4226688 h1:ax2KzoSRIZU/M0cIxri3pKxy99vniH1PVxWC6si/eZI=
+google.golang.org/genproto/googleapis/api v0.0.0-20260819154853-08b0e4226688/go.mod h1:1RJ9BQGyNdZwkGc1eTqkErfRZ6RJyYPHZo73BZ1vQqI=
+google.golang.org/genproto/googleapis/rpc v0.0.0-20260819154853-08b0e4226688 h1:cYNAzI2sUwhmCcoj9TxvihSrqsxt6uIkj3rDRhSDmW4=
+google.golang.org/genproto/googleapis/rpc v0.0.0-20260819154853-08b0e4226688/go.mod h1:DjtHYE8FKJLivXcBEjGwndXfIC23G0VpXiXKqG179uA=
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY=
@@ -1197,8 +1199,8 @@ google.golang.org/grpc v1.83.2 h1:EManeRomTObA0BU7I8vXgg/78uE5MJ9M8B39EX2WscU=
google.golang.org/grpc v1.83.2/go.mod h1:YPI1hK3kDked6iHvgX3tR0y+nX/qpMFKhPgFsokw1S8=
google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.5.1 h1:F29+wU6Ee6qgu9TddPgooOdaqsxTMunOoj8KA5yuS5A=
google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.5.1/go.mod h1:5KF+wpkbTSbGcR9zteSqZV6fqFOWBl4Yde8En8MryZA=
-google.golang.org/protobuf v1.36.11 h1:fV6ZwhNocDyBLK0dj+fg8ektcVegBBuEolpbTQyBNVE=
-google.golang.org/protobuf v1.36.11/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco=
+google.golang.org/protobuf v1.36.12 h1:pJOKDDOyeXErUroCihFAd5LQuwXBSpVnKGrj5o/fwxc=
+google.golang.org/protobuf v1.36.12/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
diff --git a/go.work b/go.work
index 38ebce6f7..957f5b9c5 100644
--- a/go.work
+++ b/go.work
@@ -1,3 +1,3 @@
-go 1.25.7
+go 1.26.0
use .
diff --git a/go.work.sum b/go.work.sum
index 64c5c37c6..a0018cea4 100644
--- a/go.work.sum
+++ b/go.work.sum
@@ -4,6 +4,7 @@ buf.build/gen/go/bufbuild/protovalidate/connectrpc/go v1.19.0-20250717185734-6c6
buf.build/gen/go/bufbuild/protovalidate/connectrpc/go v1.19.0-20250717185734-6c6e0d3c608e.1/go.mod h1:4TTUoOHJGTpciUKRMv3Qiqi/Y0qsDPzs57CKn8f9eQI=
buf.build/go/hyperpb v0.1.0 h1:utndCev4u1XvvCqcpmqLnYuaqTvVlLSFDc87mW7iQKA=
buf.build/go/hyperpb v0.1.0/go.mod h1:EZWL//pO7VKbCxzZU0JlTzFDGmfN5reHshsFHOu3AKI=
+buf.build/go/hyperpb v0.1.3/go.mod h1:IHXAM5qnS0/Fsnd7/HGDghFNvUET646WoHmq1FDZXIE=
cloud.google.com/go/accessapproval v1.8.7 h1:Sc9ZjxFBEM/PoAxNlUwVGDcv8DYyjLYWDxHlzPG0q5I=
cloud.google.com/go/accessapproval v1.8.7/go.mod h1:BFvZOW4GJjJnl6aA/YDEg0TGViFHyusa/bMdcVFmh8A=
cloud.google.com/go/accessapproval v1.8.8/go.mod h1:RFwPY9JDKseP4gJrX1BlAVsP5O6kI8NdGlTmaeDefmk=
@@ -545,6 +546,7 @@ golang.org/x/telemetry v0.0.0-20260209163413-e7419c687ee4/go.mod h1:g5NllXBEermZ
golang.org/x/telemetry v0.0.0-20260409153401-be6f6cb8b1fa/go.mod h1:kHjTxDEnAu6/Nl9lDkzjWpR+bmKfxeiRuSDlsMb70gE=
golang.org/x/telemetry v0.0.0-20260625142307-59b4966ccb57/go.mod h1:3AWMyWHS+caVoiEXpiq6+tzKA40J4vQT3MYr80ZtQpc=
golang.org/x/telemetry v0.0.0-20260708182218-49f421fb7959/go.mod h1:LV7u5Oco+Z/g6XI7PqN+EUUUGGkEcmB1uj2ceI0fOVg=
+golang.org/x/telemetry v0.0.0-20260811182544-a038080d80e5/go.mod h1:LVehoXe41cL5SCVQilsV7Gg6BNG+Js6P9PhSbYTIUkQ=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE=
google.golang.org/appengine v1.6.8 h1:IhEN5q69dyKagZPYMSdIjS2HqprW324FRQZJcGqPAsM=
google.golang.org/appengine v1.6.8/go.mod h1:1jJ3jBArFh5pcgW8gCtRJnepW8FzD1V44FJffLiz/Ds=
diff --git a/internal/servers/bundle_server.go b/internal/servers/bundle_server.go
index 83336d0e8..b98a09591 100644
--- a/internal/servers/bundle_server.go
+++ b/internal/servers/bundle_server.go
@@ -7,6 +7,8 @@ import (
otelCodes "go.opentelemetry.io/otel/codes"
"google.golang.org/grpc/status"
+ "buf.build/go/protovalidate"
+
"github.com/Permify/permify/internal"
"github.com/Permify/permify/internal/storage"
"github.com/Permify/permify/internal/validation"
@@ -36,7 +38,7 @@ func (r *BundleServer) Write(ctx context.Context, request *v1.BundleWriteRequest
ctx, span := internal.Tracer.Start(ctx, "bundle.write")
defer span.End()
- v := request.Validate()
+ v := protovalidate.Validate(request)
if v != nil {
return nil, status.Error(GetStatus(v), v.Error()) // Return validation error
}
@@ -77,7 +79,7 @@ func (r *BundleServer) Read(ctx context.Context, request *v1.BundleReadRequest)
ctx, span := internal.Tracer.Start(ctx, "bundle.read")
defer span.End()
- v := request.Validate()
+ v := protovalidate.Validate(request)
if v != nil {
return nil, status.Error(GetStatus(v), v.Error()) // Return validation error
}
@@ -100,7 +102,7 @@ func (r *BundleServer) Delete(ctx context.Context, request *v1.BundleDeleteReque
ctx, span := internal.Tracer.Start(ctx, "bundle.delete")
defer span.End()
- v := request.Validate()
+ v := protovalidate.Validate(request)
if v != nil {
return nil, status.Error(GetStatus(v), v.Error()) // Return validation error
}
diff --git a/internal/servers/data_server.go b/internal/servers/data_server.go
index ba7eb6378..ac24d30ce 100644
--- a/internal/servers/data_server.go
+++ b/internal/servers/data_server.go
@@ -4,6 +4,7 @@ import (
"context"
"log/slog"
+ "buf.build/go/protovalidate"
otelCodes "go.opentelemetry.io/otel/codes"
api "go.opentelemetry.io/otel/metric"
"google.golang.org/grpc/status"
@@ -67,7 +68,7 @@ func (r *DataServer) ReadRelationships(ctx context.Context, request *v1.Relation
size = 50
}
- v := request.Validate()
+ v := protovalidate.Validate(request)
if v != nil {
return nil, status.Error(GetStatus(v), v.Error()) // Return validation error
}
@@ -116,7 +117,7 @@ func (r *DataServer) ReadAttributes(ctx context.Context, request *v1.AttributeRe
size = 50
}
- v := request.Validate()
+ v := protovalidate.Validate(request)
if v != nil {
return nil, status.Error(GetStatus(v), v.Error()) // Return validation error
}
@@ -160,7 +161,7 @@ func (r *DataServer) Write(ctx context.Context, request *v1.DataWriteRequest) (*
ctx, span := internal.Tracer.Start(ctx, "data.write")
defer span.End()
- v := request.Validate()
+ v := protovalidate.Validate(request)
if v != nil {
return nil, status.Error(GetStatus(v), v.Error()) // Return validation error
}
@@ -256,7 +257,7 @@ func (r *DataServer) WriteRelationships(ctx context.Context, request *v1.Relatio
ctx, span := internal.Tracer.Start(ctx, "relationships.write")
defer span.End()
- v := request.Validate()
+ v := protovalidate.Validate(request)
if v != nil {
return nil, status.Error(GetStatus(v), v.Error()) // Return validation error
}
@@ -322,7 +323,7 @@ func (r *DataServer) Delete(ctx context.Context, request *v1.DataDeleteRequest)
ctx, span := internal.Tracer.Start(ctx, "data.delete")
defer span.End()
- v := request.Validate()
+ v := protovalidate.Validate(request)
if v != nil {
return nil, status.Error(GetStatus(v), v.Error()) // Return validation error
}
@@ -352,7 +353,7 @@ func (r *DataServer) DeleteRelationships(ctx context.Context, request *v1.Relati
ctx, span := internal.Tracer.Start(ctx, "relationships.delete")
defer span.End()
- v := request.Validate()
+ v := protovalidate.Validate(request)
if v != nil {
return nil, status.Error(GetStatus(v), v.Error()) // Return validation error
}
@@ -382,7 +383,7 @@ func (r *DataServer) RunBundle(ctx context.Context, request *v1.BundleRunRequest
ctx, span := internal.Tracer.Start(ctx, "bundle.run")
defer span.End()
- v := request.Validate()
+ v := protovalidate.Validate(request)
if v != nil {
return nil, status.Error(GetStatus(v), v.Error()) // Return validation error
}
diff --git a/internal/servers/permission_server.go b/internal/servers/permission_server.go
index 1fc14ce15..a4a879d51 100644
--- a/internal/servers/permission_server.go
+++ b/internal/servers/permission_server.go
@@ -9,6 +9,8 @@ import (
otelCodes "go.opentelemetry.io/otel/codes"
"google.golang.org/grpc/status"
+ "buf.build/go/protovalidate"
+
"github.com/Permify/permify/internal"
"github.com/Permify/permify/internal/invoke"
v1 "github.com/Permify/permify/pkg/pb/base/v1"
@@ -33,7 +35,7 @@ func (r *PermissionServer) Check(ctx context.Context, request *v1.PermissionChec
ctx, span := internal.Tracer.Start(ctx, "permissions.check")
defer span.End()
- v := request.Validate()
+ v := protovalidate.Validate(request)
if v != nil {
return nil, status.Error(GetStatus(v), v.Error()) // Return validation error
}
@@ -103,7 +105,7 @@ func (r *PermissionServer) BulkCheck(ctx context.Context, request *v1.Permission
defer wg.Done()
// Validate individual request
- v := checkRequestItem.Validate()
+ v := protovalidate.Validate(checkRequestItem)
if v != nil {
resultChannel <- resultItem{
index: index,
@@ -185,7 +187,7 @@ func (r *PermissionServer) Expand(ctx context.Context, request *v1.PermissionExp
ctx, span := internal.Tracer.Start(ctx, "permissions.expand")
defer span.End()
- v := request.Validate()
+ v := protovalidate.Validate(request)
if v != nil {
return nil, status.Error(GetStatus(v), v.Error()) // Return validation error
}
@@ -206,7 +208,7 @@ func (r *PermissionServer) LookupEntity(ctx context.Context, request *v1.Permiss
ctx, span := internal.Tracer.Start(ctx, "permissions.lookup-entity")
defer span.End()
- v := request.Validate()
+ v := protovalidate.Validate(request)
if v != nil {
return nil, status.Error(GetStatus(v), v.Error()) // Return validation error
}
@@ -227,7 +229,7 @@ func (r *PermissionServer) LookupEntityStream(request *v1.PermissionLookupEntity
ctx, span := internal.Tracer.Start(server.Context(), "permissions.lookup-entity-stream")
defer span.End()
- v := request.Validate()
+ v := protovalidate.Validate(request)
if v != nil {
return v
}
@@ -248,7 +250,7 @@ func (r *PermissionServer) LookupSubject(ctx context.Context, request *v1.Permis
ctx, span := internal.Tracer.Start(ctx, "permissions.lookup-subject")
defer span.End()
- v := request.Validate()
+ v := protovalidate.Validate(request)
if v != nil {
return nil, status.Error(GetStatus(v), v.Error()) // Return validation error
}
@@ -269,7 +271,7 @@ func (r *PermissionServer) SubjectPermission(ctx context.Context, request *v1.Pe
ctx, span := internal.Tracer.Start(ctx, "permissions.subject-permission")
defer span.End()
- v := request.Validate()
+ v := protovalidate.Validate(request)
if v != nil {
return nil, status.Error(GetStatus(v), v.Error()) // Return validation error
}
diff --git a/internal/servers/server_behavior_test.go b/internal/servers/server_behavior_test.go
index 9c91fc50c..6c7e487ef 100644
--- a/internal/servers/server_behavior_test.go
+++ b/internal/servers/server_behavior_test.go
@@ -13,6 +13,7 @@ import (
"github.com/grpc-ecosystem/go-grpc-middleware/v2/interceptors/logging"
gwruntime "github.com/grpc-ecosystem/grpc-gateway/v2/runtime"
+ "google.golang.org/grpc"
"google.golang.org/grpc/codes"
health "google.golang.org/grpc/health/grpc_health_v1"
"google.golang.org/grpc/status"
@@ -173,6 +174,30 @@ func (f *fakePermissionInvoker) SubjectPermission(_ context.Context, request *v1
}, nil
}
+type fakeServerStream struct {
+ grpc.ServerStream
+}
+
+func (f *fakeServerStream) Context() context.Context {
+ return context.Background()
+}
+
+type fakeLookupEntityStreamServer struct {
+ fakeServerStream
+}
+
+func (f *fakeLookupEntityStreamServer) Send(*v1.PermissionLookupEntityStreamResponse) error {
+ return nil
+}
+
+type fakeWatchStreamServer struct {
+ fakeServerStream
+}
+
+func (f *fakeWatchStreamServer) Send(*v1.WatchResponse) error {
+ return nil
+}
+
type testContextKey struct{}
func testEntity() *v1.Entity {
@@ -405,6 +430,214 @@ func TestPermissionServerValidationAndInvokerErrors(t *testing.T) {
}
}
+func TestPermissionServerBulkCheckItemValidation(t *testing.T) {
+ invoker := &fakePermissionInvoker{}
+ server := NewPermissionServer(invoker)
+
+ tests := []struct {
+ name string
+ permission string
+ wantDenied bool
+ }{
+ {name: "empty permission", permission: "", wantDenied: true},
+ {name: "permission longer than 64 bytes", permission: strings.Repeat("a", 65), wantDenied: true},
+ }
+
+ for _, tc := range tests {
+ t.Run(tc.name, func(t *testing.T) {
+ invoker.checkReq = nil
+ bulk, err := server.BulkCheck(context.Background(), &v1.PermissionBulkCheckRequest{
+ TenantId: "tenant-1",
+ Items: []*v1.PermissionBulkCheckRequestItem{{
+ Entity: testEntity(),
+ Permission: tc.permission,
+ Subject: testSubject(),
+ }},
+ })
+ if err != nil {
+ t.Fatalf("unexpected bulk check error: %v", err)
+ }
+ if len(bulk.GetResults()) != 1 {
+ t.Fatalf("expected 1 result, got %d", len(bulk.GetResults()))
+ }
+ denied := bulk.GetResults()[0].GetCan() == v1.CheckResult_CHECK_RESULT_DENIED
+ if denied != tc.wantDenied {
+ t.Fatalf("denied = %v, want %v", denied, tc.wantDenied)
+ }
+ if tc.wantDenied && invoker.checkReq != nil {
+ t.Fatal("invalid bulk item should not reach invoker")
+ }
+ })
+ }
+}
+
+func TestPermissionServerLookupEntityStreamValidation(t *testing.T) {
+ invoker := &fakePermissionInvoker{}
+ server := NewPermissionServer(invoker)
+
+ tests := []struct {
+ name string
+ tenantID string
+ }{
+ {name: "empty tenant_id", tenantID: ""},
+ {name: "tenant_id longer than 128 bytes", tenantID: strings.Repeat("a", 129)},
+ }
+
+ for _, tc := range tests {
+ t.Run(tc.name, func(t *testing.T) {
+ invoker.lookupEntityReq = nil
+ req := validPermissionLookupEntityRequest()
+ req.TenantId = tc.tenantID
+ err := server.LookupEntityStream(req, &fakeLookupEntityStreamServer{})
+ if err == nil {
+ t.Fatal("expected validation to fail")
+ }
+ if invoker.lookupEntityReq != nil {
+ t.Fatal("invalid lookup entity stream request should not reach invoker")
+ }
+ })
+ }
+}
+
+func TestDataServerValidation(t *testing.T) {
+ server := NewDataServer(nil, nil, nil, nil)
+ ctx := context.Background()
+
+ tenantIDs := []struct {
+ name string
+ id string
+ }{
+ {name: "empty tenant_id", id: ""},
+ {name: "tenant_id longer than 128 bytes", id: strings.Repeat("a", 129)},
+ }
+
+ methods := []struct {
+ name string
+ call func(tenantID string) error
+ }{
+ {
+ name: "ReadRelationships",
+ call: func(tenantID string) error {
+ _, err := server.ReadRelationships(ctx, &v1.RelationshipReadRequest{
+ TenantId: tenantID,
+ Metadata: &v1.RelationshipReadRequestMetadata{},
+ Filter: &v1.TupleFilter{},
+ })
+ return err
+ },
+ },
+ {
+ name: "ReadAttributes",
+ call: func(tenantID string) error {
+ _, err := server.ReadAttributes(ctx, &v1.AttributeReadRequest{
+ TenantId: tenantID,
+ Metadata: &v1.AttributeReadRequestMetadata{},
+ Filter: &v1.AttributeFilter{},
+ })
+ return err
+ },
+ },
+ {
+ name: "Write",
+ call: func(tenantID string) error {
+ _, err := server.Write(ctx, &v1.DataWriteRequest{
+ TenantId: tenantID,
+ Metadata: &v1.DataWriteRequestMetadata{},
+ })
+ return err
+ },
+ },
+ {
+ name: "WriteRelationships",
+ call: func(tenantID string) error {
+ _, err := server.WriteRelationships(ctx, &v1.RelationshipWriteRequest{
+ TenantId: tenantID,
+ Metadata: &v1.RelationshipWriteRequestMetadata{},
+ Tuples: []*v1.Tuple{{Entity: testEntity(), Relation: "viewer", Subject: testSubject()}},
+ })
+ return err
+ },
+ },
+ {
+ name: "Delete",
+ call: func(tenantID string) error {
+ _, err := server.Delete(ctx, &v1.DataDeleteRequest{
+ TenantId: tenantID,
+ TupleFilter: &v1.TupleFilter{
+ Entity: &v1.EntityFilter{Type: "document", Ids: []string{"document-1"}},
+ Relation: "viewer",
+ Subject: &v1.SubjectFilter{Type: "user", Ids: []string{"user-1"}},
+ },
+ AttributeFilter: &v1.AttributeFilter{},
+ })
+ return err
+ },
+ },
+ {
+ name: "DeleteRelationships",
+ call: func(tenantID string) error {
+ _, err := server.DeleteRelationships(ctx, &v1.RelationshipDeleteRequest{
+ TenantId: tenantID,
+ Filter: &v1.TupleFilter{
+ Entity: &v1.EntityFilter{Type: "document", Ids: []string{"document-1"}},
+ Relation: "viewer",
+ Subject: &v1.SubjectFilter{Type: "user", Ids: []string{"user-1"}},
+ },
+ })
+ return err
+ },
+ },
+ {
+ name: "RunBundle",
+ call: func(tenantID string) error {
+ _, err := server.RunBundle(ctx, &v1.BundleRunRequest{TenantId: tenantID})
+ return err
+ },
+ },
+ }
+
+ for _, method := range methods {
+ for _, tenant := range tenantIDs {
+ t.Run(method.name+"/"+tenant.name, func(t *testing.T) {
+ if err := method.call(tenant.id); err == nil {
+ t.Fatal("expected validation to fail")
+ }
+ })
+ }
+ }
+
+ t.Run("WriteRelationships/empty tuples", func(t *testing.T) {
+ _, err := server.WriteRelationships(ctx, &v1.RelationshipWriteRequest{
+ TenantId: "a",
+ Metadata: &v1.RelationshipWriteRequestMetadata{},
+ })
+ if err == nil {
+ t.Fatal("expected validation to fail")
+ }
+ })
+}
+
+func TestWatchServerValidation(t *testing.T) {
+ server := NewWatchServer(nil, nil)
+
+ tests := []struct {
+ name string
+ tenantID string
+ }{
+ {name: "empty tenant_id", tenantID: ""},
+ {name: "tenant_id longer than 128 bytes", tenantID: strings.Repeat("a", 129)},
+ }
+
+ for _, tc := range tests {
+ t.Run(tc.name, func(t *testing.T) {
+ err := server.Watch(&v1.WatchRequest{TenantId: tc.tenantID}, &fakeWatchStreamServer{})
+ if err == nil {
+ t.Fatal("expected validation to fail")
+ }
+ })
+ }
+}
+
func TestTenancyServer(t *testing.T) {
store := &fakeTenantStore{
tenants: []*v1.Tenant{{Id: "tenant-1", Name: "Tenant One"}},
diff --git a/internal/servers/watch_server.go b/internal/servers/watch_server.go
index f07beac9d..cdc61df14 100644
--- a/internal/servers/watch_server.go
+++ b/internal/servers/watch_server.go
@@ -1,6 +1,7 @@
package servers
import (
+ "buf.build/go/protovalidate"
"google.golang.org/grpc/status"
"github.com/Permify/permify/internal"
@@ -32,7 +33,7 @@ func (r *WatchServer) Watch(request *v1.WatchRequest, server v1.Watch_WatchServe
defer span.End() // Ensure the span ends when the function returns.
// Validate the incoming request.
- v := request.Validate()
+ v := protovalidate.Validate(request)
if v != nil {
return v // Return validation error, if any.
}
diff --git a/internal/storage/postgres/data_writer.go b/internal/storage/postgres/data_writer.go
index 1c2ada851..9d77a10b9 100644
--- a/internal/storage/postgres/data_writer.go
+++ b/internal/storage/postgres/data_writer.go
@@ -312,6 +312,7 @@ func (w *DataWriter) delete(
// Return snapshot token
return snapshot.NewToken(xid, snapshotValue).Encode(), nil
} // End Delete
+
// Helper functions for RunBundle
// RunBundle helper function
// RunBundle implementation
diff --git a/internal/storage/postgres/tenant_writer_test.go b/internal/storage/postgres/tenant_writer_test.go
index f3a3949fc..5dde173e1 100644
--- a/internal/storage/postgres/tenant_writer_test.go
+++ b/internal/storage/postgres/tenant_writer_test.go
@@ -9,12 +9,13 @@ import (
. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"
+ "github.com/rs/xid"
+
"github.com/Permify/permify/internal/storage"
"github.com/Permify/permify/pkg/database"
base "github.com/Permify/permify/pkg/pb/base/v1"
"github.com/Permify/permify/pkg/testinstance"
"github.com/Permify/permify/pkg/tuple"
- "github.com/rs/xid"
)
var _ = Describe("TenantWriter", func() {
diff --git a/pkg/database/postgres/xid8.go b/pkg/database/postgres/xid8.go
index cbfc9af19..60ce5eed9 100644
--- a/pkg/database/postgres/xid8.go
+++ b/pkg/database/postgres/xid8.go
@@ -16,7 +16,7 @@ func (x *XID8) Set(src interface{}) error {
// Get returns the underlying value
func (x XID8) Get() interface{} {
- return (pguint64)(x).Get()
+ return pguint64(x).Get()
}
// AssignTo assigns the value to the destination
@@ -36,12 +36,12 @@ func (x *XID8) DecodeBinary(ci *pgtype.ConnInfo, src []byte) error {
// EncodeText encodes to text format
func (x XID8) EncodeText(ci *pgtype.ConnInfo, buf []byte) ([]byte, error) {
- return (pguint64)(x).EncodeText(ci, buf)
+ return pguint64(x).EncodeText(ci, buf)
}
// EncodeBinary encodes to binary format
func (x XID8) EncodeBinary(ci *pgtype.ConnInfo, buf []byte) ([]byte, error) {
- return (pguint64)(x).EncodeBinary(ci, buf)
+ return pguint64(x).EncodeBinary(ci, buf)
}
// Scan implements the database/sql Scanner interface
@@ -51,5 +51,5 @@ func (x *XID8) Scan(src interface{}) error {
// Value implements the database/sql/driver Valuer interface
func (x XID8) Value() (driver.Value, error) {
- return (pguint64)(x).Value()
+ return pguint64(x).Value()
}
diff --git a/pkg/dsl/parser/parser.go b/pkg/dsl/parser/parser.go
index b65012eec..1367e26d1 100644
--- a/pkg/dsl/parser/parser.go
+++ b/pkg/dsl/parser/parser.go
@@ -131,6 +131,7 @@ func (p *Parser) previousTokenIs(tokens ...token.Type) bool { // Check if previo
} // All types checked
return false // No match found
} // End previousTokenIs
+
// peekTokenIs checks if the Parser's peekToken is any of the given token types
func (p *Parser) peekTokenIs(tokens ...token.Type) bool {
// iterate through the given token types and check if any of them match the peekToken's type
diff --git a/pkg/dsl/parser/parser_test.go b/pkg/dsl/parser/parser_test.go
index 5365decf0..1ea25832a 100644
--- a/pkg/dsl/parser/parser_test.go
+++ b/pkg/dsl/parser/parser_test.go
@@ -2,15 +2,18 @@ package parser // Parser package tests
import ( // Test imports
"testing" // Testing framework
+ . "github.com/onsi/ginkgo/v2" // BDD framework
+ . "github.com/onsi/gomega" // Matchers
+
"github.com/Permify/permify/pkg/dsl/ast" // AST types
- . "github.com/onsi/ginkgo/v2" // BDD framework
- . "github.com/onsi/gomega" // Matchers
) // End imports
+
// TestParser - Parser test suite entry point
func TestParser(t *testing.T) {
RegisterFailHandler(Fail)
RunSpecs(t, "parser-suite")
-} // End TestParser
+} // End TestParser
+
var _ = Describe("parser", func() { // Parser test suite
Context("Statement", func() {
It("Case // Test case 1 - Repository with parent and owner relations and read action", func() {
diff --git a/pkg/pb/base/v1/base.pb.go b/pkg/pb/base/v1/base.pb.go
index 9de6e7356..878f607f9 100644
--- a/pkg/pb/base/v1/base.pb.go
+++ b/pkg/pb/base/v1/base.pb.go
@@ -7,7 +7,7 @@
package basev1
import (
- _ "github.com/envoyproxy/protoc-gen-validate/validate"
+ _ "buf.build/gen/go/bufbuild/protovalidate/protocolbuffers/go/buf/validate"
v1alpha1 "google.golang.org/genproto/googleapis/api/expr/v1alpha1"
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
@@ -3280,23 +3280,23 @@ var File_base_v1_base_proto protoreflect.FileDescriptor
const file_base_v1_base_proto_rawDesc = "" +
"\n" +
- "\x12base/v1/base.proto\x12\abase.v1\x1a&google/api/expr/v1alpha1/checked.proto\x1a\x19google/protobuf/any.proto\x1a\x1cgoogle/protobuf/struct.proto\x1a\x1fgoogle/protobuf/timestamp.proto\x1a\x17validate/validate.proto\"\x92\x01\n" +
+ "\x12base/v1/base.proto\x12\abase.v1\x1a\x1bbuf/validate/validate.proto\x1a&google/api/expr/v1alpha1/checked.proto\x1a\x19google/protobuf/any.proto\x1a\x1cgoogle/protobuf/struct.proto\x1a\x1fgoogle/protobuf/timestamp.proto\"\x92\x01\n" +
"\aContext\x12&\n" +
"\x06tuples\x18\x01 \x03(\v2\x0e.base.v1.TupleR\x06tuples\x122\n" +
"\n" +
"attributes\x18\x02 \x03(\v2\x12.base.v1.AttributeR\n" +
"attributes\x12+\n" +
- "\x04data\x18\x03 \x01(\v2\x17.google.protobuf.StructR\x04data\"{\n" +
- "\x05Child\x12-\n" +
- "\x04leaf\x18\x01 \x01(\v2\r.base.v1.LeafB\b\xfaB\x05\x8a\x01\x02\x10\x01H\x00R\x04leaf\x126\n" +
- "\arewrite\x18\x02 \x01(\v2\x10.base.v1.RewriteB\b\xfaB\x05\x8a\x01\x02\x10\x01H\x00R\arewriteB\v\n" +
- "\x04type\x12\x03\xf8B\x01\"\xbb\x02\n" +
- "\x04Leaf\x12P\n" +
- "\x11computed_user_set\x18\x01 \x01(\v2\x18.base.v1.ComputedUserSetB\b\xfaB\x05\x8a\x01\x02\x10\x01H\x00R\x0fcomputedUserSet\x12N\n" +
- "\x11tuple_to_user_set\x18\x02 \x01(\v2\x17.base.v1.TupleToUserSetB\b\xfaB\x05\x8a\x01\x02\x10\x01H\x00R\x0etupleToUserSet\x12U\n" +
- "\x12computed_attribute\x18\x03 \x01(\v2\x1a.base.v1.ComputedAttributeB\b\xfaB\x05\x8a\x01\x02\x10\x01H\x00R\x11computedAttribute\x12-\n" +
- "\x04call\x18\x04 \x01(\v2\r.base.v1.CallB\b\xfaB\x05\x8a\x01\x02\x10\x01H\x00R\x04callB\v\n" +
- "\x04type\x12\x03\xf8B\x01\"\xf0\x01\n" +
+ "\x04data\x18\x03 \x01(\v2\x17.google.protobuf.StructR\x04data\"i\n" +
+ "\x05Child\x12#\n" +
+ "\x04leaf\x18\x01 \x01(\v2\r.base.v1.LeafH\x00R\x04leaf\x12,\n" +
+ "\arewrite\x18\x02 \x01(\v2\x10.base.v1.RewriteH\x00R\arewriteB\r\n" +
+ "\x04type\x12\x05\xbaH\x02\b\x01\"\x95\x02\n" +
+ "\x04Leaf\x12F\n" +
+ "\x11computed_user_set\x18\x01 \x01(\v2\x18.base.v1.ComputedUserSetH\x00R\x0fcomputedUserSet\x12D\n" +
+ "\x11tuple_to_user_set\x18\x02 \x01(\v2\x17.base.v1.TupleToUserSetH\x00R\x0etupleToUserSet\x12K\n" +
+ "\x12computed_attribute\x18\x03 \x01(\v2\x1a.base.v1.ComputedAttributeH\x00R\x11computedAttribute\x12#\n" +
+ "\x04call\x18\x04 \x01(\v2\r.base.v1.CallH\x00R\x04callB\r\n" +
+ "\x04type\x12\x05\xbaH\x02\b\x01\"\xf0\x01\n" +
"\aRewrite\x12G\n" +
"\x11rewrite_operation\x18\x01 \x01(\x0e2\x1a.base.v1.Rewrite.OperationR\x10rewriteOperation\x12*\n" +
"\bchildren\x18\x02 \x03(\v2\x0e.base.v1.ChildR\bchildren\"p\n" +
@@ -3325,7 +3325,7 @@ const file_base_v1_base_proto_rawDesc = "" +
"\x10REFERENCE_ENTITY\x10\x01\x12\x12\n" +
"\x0eREFERENCE_RULE\x10\x02\"\xdc\x06\n" +
"\x10EntityDefinition\x12.\n" +
- "\x04name\x18\x01 \x01(\tB\x1a\xfaB\x17r\x15(@2\x11^[a-zA-Z_]{1,64}$R\x04name\x12F\n" +
+ "\x04name\x18\x01 \x01(\tB\x1a\xbaH\x17r\x15(@2\x11^[a-zA-Z_]{1,64}$R\x04name\x12F\n" +
"\trelations\x18\x02 \x03(\v2(.base.v1.EntityDefinition.RelationsEntryR\trelations\x12L\n" +
"\vpermissions\x18\x03 \x03(\v2*.base.v1.EntityDefinition.PermissionsEntryR\vpermissions\x12I\n" +
"\n" +
@@ -3352,7 +3352,7 @@ const file_base_v1_base_proto_rawDesc = "" +
"\x14REFERENCE_PERMISSION\x10\x02\x12\x17\n" +
"\x13REFERENCE_ATTRIBUTE\x10\x03\"\xa3\x02\n" +
"\x0eRuleDefinition\x12.\n" +
- "\x04name\x18\x01 \x01(\tB\x1a\xfaB\x17r\x15(@2\x11^[a-zA-Z_]{1,64}$R\x04name\x12D\n" +
+ "\x04name\x18\x01 \x01(\tB\x1a\xbaH\x17r\x15(@2\x11^[a-zA-Z_]{1,64}$R\x04name\x12D\n" +
"\targuments\x18\x02 \x03(\v2&.base.v1.RuleDefinition.ArgumentsEntryR\targuments\x12E\n" +
"\n" +
"expression\x18\x03 \x01(\v2%.google.api.expr.v1alpha1.CheckedExprR\n" +
@@ -3361,20 +3361,20 @@ const file_base_v1_base_proto_rawDesc = "" +
"\x03key\x18\x01 \x01(\tR\x03key\x12,\n" +
"\x05value\x18\x02 \x01(\x0e2\x16.base.v1.AttributeTypeR\x05value:\x028\x01\"q\n" +
"\x13AttributeDefinition\x12.\n" +
- "\x04name\x18\x01 \x01(\tB\x1a\xfaB\x17r\x15(@2\x11^[a-zA-Z_]{1,64}$R\x04name\x12*\n" +
+ "\x04name\x18\x01 \x01(\tB\x1a\xbaH\x17r\x15(@2\x11^[a-zA-Z_]{1,64}$R\x04name\x12*\n" +
"\x04type\x18\x02 \x01(\x0e2\x16.base.v1.AttributeTypeR\x04type\"\x91\x01\n" +
"\x12RelationDefinition\x12.\n" +
- "\x04name\x18\x01 \x01(\tB\x1a\xfaB\x17r\x15(@2\x11^[a-zA-Z_]{1,64}$R\x04name\x12K\n" +
+ "\x04name\x18\x01 \x01(\tB\x1a\xbaH\x17r\x15(@2\x11^[a-zA-Z_]{1,64}$R\x04name\x12K\n" +
"\x13relation_references\x18\x02 \x03(\v2\x1a.base.v1.RelationReferenceR\x12relationReferences\"l\n" +
"\x14PermissionDefinition\x12.\n" +
- "\x04name\x18\x01 \x01(\tB\x1a\xfaB\x17r\x15(@2\x11^[a-zA-Z_]{1,64}$R\x04name\x12$\n" +
+ "\x04name\x18\x01 \x01(\tB\x1a\xbaH\x17r\x15(@2\x11^[a-zA-Z_]{1,64}$R\x04name\x12$\n" +
"\x05child\x18\x02 \x01(\v2\x0e.base.v1.ChildR\x05child\"~\n" +
"\x11RelationReference\x12.\n" +
- "\x04type\x18\x01 \x01(\tB\x1a\xfaB\x17r\x15(@2\x11^[a-zA-Z_]{1,64}$R\x04type\x129\n" +
- "\brelation\x18\x02 \x01(\tB\x1d\xfaB\x1ar\x18(@2\x11^[a-zA-Z_]{1,64}$\xd0\x01\x01R\brelation\"l\n" +
+ "\x04type\x18\x01 \x01(\tB\x1a\xbaH\x17r\x15(@2\x11^[a-zA-Z_]{1,64}$R\x04type\x129\n" +
+ "\brelation\x18\x02 \x01(\tB\x1d\xbaH\x1a\xd8\x01\x01r\x15(@2\x11^[a-zA-Z_]{1,64}$R\brelation\"l\n" +
"\bEntrance\x12.\n" +
- "\x04type\x18\x01 \x01(\tB\x1a\xfaB\x17r\x15(@2\x11^[a-zA-Z_]{1,64}$R\x04type\x120\n" +
- "\x05value\x18\x02 \x01(\tB\x1a\xfaB\x17r\x15(@2\x11^[a-zA-Z_]{1,64}$R\x05value\"_\n" +
+ "\x04type\x18\x01 \x01(\tB\x1a\xbaH\x17r\x15(@2\x11^[a-zA-Z_]{1,64}$R\x04type\x120\n" +
+ "\x05value\x18\x02 \x01(\tB\x1a\xbaH\x17r\x15(@2\x11^[a-zA-Z_]{1,64}$R\x05value\"_\n" +
"\bArgument\x12K\n" +
"\x12computed_attribute\x18\x01 \x01(\v2\x1a.base.v1.ComputedAttributeH\x00R\x11computedAttributeB\x06\n" +
"\x04type\"T\n" +
@@ -3382,20 +3382,20 @@ const file_base_v1_base_proto_rawDesc = "" +
"\trule_name\x18\x01 \x01(\tR\bruleName\x12/\n" +
"\targuments\x18\x02 \x03(\v2\x11.base.v1.ArgumentR\targuments\"C\n" +
"\x11ComputedAttribute\x12.\n" +
- "\x04name\x18\x01 \x01(\tB\x1a\xfaB\x17r\x15(@2\x11^[a-zA-Z_]{1,64}$R\x04name\"I\n" +
+ "\x04name\x18\x01 \x01(\tB\x1a\xbaH\x17r\x15(@2\x11^[a-zA-Z_]{1,64}$R\x04name\"I\n" +
"\x0fComputedUserSet\x126\n" +
- "\brelation\x18\x01 \x01(\tB\x1a\xfaB\x17r\x15(@2\x11^[a-zA-Z_]{1,64}$R\brelation\"u\n" +
+ "\brelation\x18\x01 \x01(\tB\x1a\xbaH\x17r\x15(@2\x11^[a-zA-Z_]{1,64}$R\brelation\"u\n" +
"\x0eTupleToUserSet\x12-\n" +
"\btupleSet\x18\x01 \x01(\v2\x11.base.v1.TupleSetR\btupleSet\x124\n" +
"\bcomputed\x18\x02 \x01(\v2\x18.base.v1.ComputedUserSetR\bcomputed\"B\n" +
"\bTupleSet\x126\n" +
- "\brelation\x18\x01 \x01(\tB\x1a\xfaB\x17r\x15(@2\x11^[a-zA-Z_]{1,64}$R\brelation\"\xa8\x01\n" +
- "\x05Tuple\x121\n" +
- "\x06entity\x18\x01 \x01(\v2\x0f.base.v1.EntityB\b\xfaB\x05\x8a\x01\x02\x10\x01R\x06entity\x126\n" +
- "\brelation\x18\x02 \x01(\tB\x1a\xfaB\x17r\x15(@2\x11^[a-zA-Z_]{1,64}$R\brelation\x124\n" +
- "\asubject\x18\x03 \x01(\v2\x10.base.v1.SubjectB\b\xfaB\x05\x8a\x01\x02\x10\x01R\asubject\"\x88\x01\n" +
- "\tAttribute\x121\n" +
- "\x06entity\x18\x01 \x01(\v2\x0f.base.v1.EntityB\b\xfaB\x05\x8a\x01\x02\x10\x01R\x06entity\x12\x1c\n" +
+ "\brelation\x18\x01 \x01(\tB\x1a\xbaH\x17r\x15(@2\x11^[a-zA-Z_]{1,64}$R\brelation\"\xa4\x01\n" +
+ "\x05Tuple\x12/\n" +
+ "\x06entity\x18\x01 \x01(\v2\x0f.base.v1.EntityB\x06\xbaH\x03\xc8\x01\x01R\x06entity\x126\n" +
+ "\brelation\x18\x02 \x01(\tB\x1a\xbaH\x17r\x15(@2\x11^[a-zA-Z_]{1,64}$R\brelation\x122\n" +
+ "\asubject\x18\x03 \x01(\v2\x10.base.v1.SubjectB\x06\xbaH\x03\xc8\x01\x01R\asubject\"\x86\x01\n" +
+ "\tAttribute\x12/\n" +
+ "\x06entity\x18\x01 \x01(\v2\x0f.base.v1.EntityB\x06\xbaH\x03\xc8\x01\x01R\x06entity\x12\x1c\n" +
"\tattribute\x18\x02 \x01(\tR\tattribute\x12*\n" +
"\x05value\x18\x03 \x01(\v2\x14.google.protobuf.AnyR\x05value\"0\n" +
"\x06Tuples\x12&\n" +
@@ -3406,15 +3406,15 @@ const file_base_v1_base_proto_rawDesc = "" +
"attributes\x18\x01 \x03(\v2\x12.base.v1.AttributeR\n" +
"attributes\"u\n" +
"\x06Entity\x12.\n" +
- "\x04type\x18\x01 \x01(\tB\x1a\xfaB\x17r\x15(@2\x11^[a-zA-Z_]{1,64}$R\x04type\x12;\n" +
- "\x02id\x18\x02 \x01(\tB+\xfaB(r&(\x80\x012!^([a-zA-Z0-9_\\-@\\.:+]{1,128}|\\*)$R\x02id\"~\n" +
- "\x11EntityAndRelation\x121\n" +
- "\x06entity\x18\x01 \x01(\v2\x0f.base.v1.EntityB\b\xfaB\x05\x8a\x01\x02\x10\x01R\x06entity\x126\n" +
- "\brelation\x18\x02 \x01(\tB\x1a\xfaB\x17r\x15(@2\x11^[a-zA-Z_]{1,64}$R\brelation\"\xb1\x01\n" +
+ "\x04type\x18\x01 \x01(\tB\x1a\xbaH\x17r\x15(@2\x11^[a-zA-Z_]{1,64}$R\x04type\x12;\n" +
+ "\x02id\x18\x02 \x01(\tB+\xbaH(r&(\x80\x012!^([a-zA-Z0-9_\\-@\\.:+]{1,128}|\\*)$R\x02id\"|\n" +
+ "\x11EntityAndRelation\x12/\n" +
+ "\x06entity\x18\x01 \x01(\v2\x0f.base.v1.EntityB\x06\xbaH\x03\xc8\x01\x01R\x06entity\x126\n" +
+ "\brelation\x18\x02 \x01(\tB\x1a\xbaH\x17r\x15(@2\x11^[a-zA-Z_]{1,64}$R\brelation\"\xb1\x01\n" +
"\aSubject\x12.\n" +
- "\x04type\x18\x01 \x01(\tB\x1a\xfaB\x17r\x15(@2\x11^[a-zA-Z_]{1,64}$R\x04type\x12;\n" +
- "\x02id\x18\x02 \x01(\tB+\xfaB(r&(\x80\x012!^([a-zA-Z0-9_\\-@\\.:+]{1,128}|\\*)$R\x02id\x129\n" +
- "\brelation\x18\x03 \x01(\tB\x1d\xfaB\x1ar\x18(@2\x11^[a-zA-Z_]{1,64}$\xd0\x01\x01R\brelation\"`\n" +
+ "\x04type\x18\x01 \x01(\tB\x1a\xbaH\x17r\x15(@2\x11^[a-zA-Z_]{1,64}$R\x04type\x12;\n" +
+ "\x02id\x18\x02 \x01(\tB+\xbaH(r&(\x80\x012!^([a-zA-Z0-9_\\-@\\.:+]{1,128}|\\*)$R\x02id\x129\n" +
+ "\brelation\x18\x03 \x01(\tB\x1d\xbaH\x1a\xd8\x01\x01r\x15(@2\x11^[a-zA-Z_]{1,64}$R\brelation\"`\n" +
"\x0fAttributeFilter\x12-\n" +
"\x06entity\x18\x01 \x01(\v2\x15.base.v1.EntityFilterR\x06entity\x12\x1e\n" +
"\n" +
@@ -3422,7 +3422,7 @@ const file_base_v1_base_proto_rawDesc = "" +
"attributes\"\xa9\x01\n" +
"\vTupleFilter\x12-\n" +
"\x06entity\x18\x01 \x01(\v2\x15.base.v1.EntityFilterR\x06entity\x129\n" +
- "\brelation\x18\x02 \x01(\tB\x1d\xfaB\x1ar\x18(@2\x11^[a-zA-Z_]{1,64}$\xd0\x01\x01R\brelation\x120\n" +
+ "\brelation\x18\x02 \x01(\tB\x1d\xbaH\x1a\xd8\x01\x01r\x15(@2\x11^[a-zA-Z_]{1,64}$R\brelation\x120\n" +
"\asubject\x18\x03 \x01(\v2\x16.base.v1.SubjectFilterR\asubject\"4\n" +
"\fEntityFilter\x12\x12\n" +
"\x04type\x18\x01 \x01(\tR\x04type\x12\x10\n" +
@@ -3430,7 +3430,7 @@ const file_base_v1_base_proto_rawDesc = "" +
"\rSubjectFilter\x12\x12\n" +
"\x04type\x18\x01 \x01(\tR\x04type\x12\x10\n" +
"\x03ids\x18\x02 \x03(\tR\x03ids\x129\n" +
- "\brelation\x18\x03 \x01(\tB\x1d\xfaB\x1ar\x18(@2\x11^[a-zA-Z_]{1,64}$\xd0\x01\x01R\brelation\"\xf0\x01\n" +
+ "\brelation\x18\x03 \x01(\tB\x1d\xbaH\x1a\xd8\x01\x01r\x15(@2\x11^[a-zA-Z_]{1,64}$R\brelation\"\xf0\x01\n" +
"\x0eExpandTreeNode\x12?\n" +
"\toperation\x18\x01 \x01(\x0e2!.base.v1.ExpandTreeNode.OperationR\toperation\x12+\n" +
"\bchildren\x18\x02 \x03(\v2\x0f.base.v1.ExpandR\bchildren\"p\n" +
@@ -3447,13 +3447,13 @@ const file_base_v1_base_proto_rawDesc = "" +
"\targuments\x18\x03 \x03(\v2\x11.base.v1.ArgumentR\targuments\x121\n" +
"\x06expand\x18\x04 \x01(\v2\x17.base.v1.ExpandTreeNodeH\x00R\x06expand\x12)\n" +
"\x04leaf\x18\x05 \x01(\v2\x13.base.v1.ExpandLeafH\x00R\x04leafB\x06\n" +
- "\x04node\"\xa3\x01\n" +
+ "\x04node\"\xa5\x01\n" +
"\n" +
"ExpandLeaf\x12/\n" +
"\bsubjects\x18\x01 \x01(\v2\x11.base.v1.SubjectsH\x00R\bsubjects\x12)\n" +
"\x06values\x18\x02 \x01(\v2\x0f.base.v1.ValuesH\x00R\x06values\x12,\n" +
- "\x05value\x18\x03 \x01(\v2\x14.google.protobuf.AnyH\x00R\x05valueB\v\n" +
- "\x04type\x12\x03\xf8B\x01\"\x8e\x01\n" +
+ "\x05value\x18\x03 \x01(\v2\x14.google.protobuf.AnyH\x00R\x05valueB\r\n" +
+ "\x04type\x12\x05\xbaH\x02\b\x01\"\x8e\x01\n" +
"\x06Values\x123\n" +
"\x06values\x18\x01 \x03(\v2\x1b.base.v1.Values.ValuesEntryR\x06values\x1aO\n" +
"\vValuesEntry\x12\x10\n" +
@@ -3471,7 +3471,7 @@ const file_base_v1_base_proto_rawDesc = "" +
"\n" +
"snap_token\x18\x01 \x01(\tR\n" +
"snap_token\x127\n" +
- "\fdata_changes\x18\x02 \x03(\v2\x13.base.v1.DataChangeR\fdata_changes\"\x86\x02\n" +
+ "\fdata_changes\x18\x02 \x03(\v2\x13.base.v1.DataChangeR\fdata_changes\"\x88\x02\n" +
"\n" +
"DataChange\x12;\n" +
"\toperation\x18\x01 \x01(\x0e2\x1d.base.v1.DataChange.OperationR\toperation\x12&\n" +
@@ -3480,8 +3480,8 @@ const file_base_v1_base_proto_rawDesc = "" +
"\tOperation\x12\x19\n" +
"\x15OPERATION_UNSPECIFIED\x10\x00\x12\x14\n" +
"\x10OPERATION_CREATE\x10\x01\x12\x14\n" +
- "\x10OPERATION_DELETE\x10\x02B\v\n" +
- "\x04type\x12\x03\xf8B\x01\"!\n" +
+ "\x10OPERATION_DELETE\x10\x02B\r\n" +
+ "\x04type\x12\x05\xbaH\x02\b\x01\"!\n" +
"\vStringValue\x12\x12\n" +
"\x04data\x18\x01 \x01(\tR\x04data\"\"\n" +
"\fIntegerValue\x12\x12\n" +
diff --git a/pkg/pb/base/v1/service.pb.go b/pkg/pb/base/v1/service.pb.go
index fe4c4ce86..a6f12b196 100644
--- a/pkg/pb/base/v1/service.pb.go
+++ b/pkg/pb/base/v1/service.pb.go
@@ -7,7 +7,7 @@
package basev1
import (
- _ "github.com/envoyproxy/protoc-gen-validate/validate"
+ _ "buf.build/gen/go/bufbuild/protovalidate/protocolbuffers/go/buf/validate"
_ "github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-openapiv2/options"
_ "google.golang.org/genproto/googleapis/api/annotations"
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
@@ -3898,15 +3898,15 @@ var File_base_v1_service_proto protoreflect.FileDescriptor
const file_base_v1_service_proto_rawDesc = "" +
"\n" +
- "\x15base/v1/service.proto\x12\abase.v1\x1a\x12base/v1/base.proto\x1a\x1cgoogle/api/annotations.proto\x1a.protoc-gen-openapiv2/options/annotations.proto\x1a\x17validate/validate.proto\"\x80\a\n" +
- "\x16PermissionCheckRequest\x12\xaa\x02\n" +
- "\ttenant_id\x18\x01 \x01(\tB\x8b\x02\x92A\xd9\x012\xd6\x01Identifier of the tenant, if you are not using multi-tenancy (have only one tenant) use pre-inserted tenant t1 for this field. Required, and must match the pattern \\“[a-zA-Z0-9-,]+\\“, max 64 bytes.\xfaB+r)(\x80\x012!^([a-zA-Z0-9_\\-@\\.:+]{1,128}|\\*)$\xd0\x01\x00R\ttenant_id\x12M\n" +
- "\bmetadata\x18\x02 \x01(\v2'.base.v1.PermissionCheckRequestMetadataB\b\xfaB\x05\x8a\x01\x02\x10\x01R\bmetadata\x12D\n" +
- "\x06entity\x18\x03 \x01(\v2\x0f.base.v1.EntityB\x1b\x92A\x10J\x0e\"repository:1\"\xfaB\x05\x8a\x01\x02\x10\x01R\x06entity\x12v\n" +
+ "\x15base/v1/service.proto\x12\abase.v1\x1a\x12base/v1/base.proto\x1a\x1bbuf/validate/validate.proto\x1a\x1cgoogle/api/annotations.proto\x1a.protoc-gen-openapiv2/options/annotations.proto\"\xf4\x06\n" +
+ "\x16PermissionCheckRequest\x12\xa7\x02\n" +
+ "\ttenant_id\x18\x01 \x01(\tB\x88\x02\x92A\xd9\x012\xd6\x01Identifier of the tenant, if you are not using multi-tenancy (have only one tenant) use pre-inserted tenant t1 for this field. Required, and must match the pattern \\“[a-zA-Z0-9-,]+\\“, max 64 bytes.\xbaH(r&(\x80\x012!^([a-zA-Z0-9_\\-@\\.:+]{1,128}|\\*)$R\ttenant_id\x12K\n" +
+ "\bmetadata\x18\x02 \x01(\v2'.base.v1.PermissionCheckRequestMetadataB\x06\xbaH\x03\xc8\x01\x01R\bmetadata\x12B\n" +
+ "\x06entity\x18\x03 \x01(\v2\x0f.base.v1.EntityB\x19\x92A\x10J\x0e\"repository:1\"\xbaH\x03\xc8\x01\x01R\x06entity\x12s\n" +
"\n" +
- "permission\x18\x04 \x01(\tBV\x92A624The action the user wants to perform on the resource\xfaB\x1ar\x18(@2\x11^[a-zA-Z_]{1,64}$\xd0\x01\x00R\n" +
- "permission\x124\n" +
- "\asubject\x18\x05 \x01(\v2\x10.base.v1.SubjectB\b\xfaB\x05\x8a\x01\x02\x10\x01R\asubject\x12\xc4\x01\n" +
+ "permission\x18\x04 \x01(\tBS\x92A624The action the user wants to perform on the resource\xbaH\x17r\x15(@2\x11^[a-zA-Z_]{1,64}$R\n" +
+ "permission\x122\n" +
+ "\asubject\x18\x05 \x01(\v2\x10.base.v1.SubjectB\x06\xbaH\x03\xc8\x01\x01R\asubject\x12\xc4\x01\n" +
"\acontext\x18\x06 \x01(\v2\x10.base.v1.ContextB\x97\x01\x92A\x93\x012\x90\x01Contextual data that can be dynamically added to permission check requests. See details on [Contextual Data](../../operations/contextual-tuples)R\acontext\x12/\n" +
"\targuments\x18\a \x03(\v2\x11.base.v1.ArgumentR\targuments\"\xb2\x02\n" +
"\x1ePermissionCheckRequestMetadata\x12&\n" +
@@ -3914,33 +3914,33 @@ const file_base_v1_service_proto_rawDesc = "" +
"\n" +
"snap_token\x18\x02 \x01(\tBi\x92Af2dThe snap token to avoid stale cache, see more details on [Snap Tokens](../../operations/snap-tokens)R\n" +
"snap_token\x12\\\n" +
- "\x05depth\x18\x03 \x01(\x05BF\x92A<2:Query limit when if recursive database queries got in loop\xfaB\x04\x1a\x02(\x03R\x05depth\"\x87\x01\n" +
+ "\x05depth\x18\x03 \x01(\x05BF\x92A<2:Query limit when if recursive database queries got in loop\xbaH\x04\x1a\x02(\x03R\x05depth\"\x87\x01\n" +
"\x17PermissionCheckResponse\x12&\n" +
"\x03can\x18\x01 \x01(\x0e2\x14.base.v1.CheckResultR\x03can\x12D\n" +
"\bmetadata\x18\x02 \x01(\v2(.base.v1.PermissionCheckResponseMetadataR\bmetadata\"C\n" +
"\x1fPermissionCheckResponseMetadata\x12 \n" +
- "\vcheck_count\x18\x01 \x01(\x05R\vcheck_count\"\x94\x02\n" +
- "\x1ePermissionBulkCheckRequestItem\x12D\n" +
- "\x06entity\x18\x01 \x01(\v2\x0f.base.v1.EntityB\x1b\x92A\x10J\x0e\"repository:1\"\xfaB\x05\x8a\x01\x02\x10\x01R\x06entity\x12v\n" +
+ "\vcheck_count\x18\x01 \x01(\x05R\vcheck_count\"\x8d\x02\n" +
+ "\x1ePermissionBulkCheckRequestItem\x12B\n" +
+ "\x06entity\x18\x01 \x01(\v2\x0f.base.v1.EntityB\x19\x92A\x10J\x0e\"repository:1\"\xbaH\x03\xc8\x01\x01R\x06entity\x12s\n" +
"\n" +
- "permission\x18\x02 \x01(\tBV\x92A624The action the user wants to perform on the resource\xfaB\x1ar\x18(@2\x11^[a-zA-Z_]{1,64}$\xd0\x01\x00R\n" +
- "permission\x124\n" +
- "\asubject\x18\x03 \x01(\v2\x10.base.v1.SubjectB\b\xfaB\x05\x8a\x01\x02\x10\x01R\asubject\"\xdb\x05\n" +
- "\x1aPermissionBulkCheckRequest\x12\xaa\x02\n" +
- "\ttenant_id\x18\x01 \x01(\tB\x8b\x02\x92A\xd9\x012\xd6\x01Identifier of the tenant, if you are not using multi-tenancy (have only one tenant) use pre-inserted tenant t1 for this field. Required, and must match the pattern \\“[a-zA-Z0-9-,]+\\“, max 64 bytes.\xfaB+r)(\x80\x012!^([a-zA-Z0-9_\\-@\\.:+]{1,128}|\\*)$\xd0\x01\x00R\ttenant_id\x12M\n" +
- "\bmetadata\x18\x02 \x01(\v2'.base.v1.PermissionCheckRequestMetadataB\b\xfaB\x05\x8a\x01\x02\x10\x01R\bmetadata\x12I\n" +
+ "permission\x18\x02 \x01(\tBS\x92A624The action the user wants to perform on the resource\xbaH\x17r\x15(@2\x11^[a-zA-Z_]{1,64}$R\n" +
+ "permission\x122\n" +
+ "\asubject\x18\x03 \x01(\v2\x10.base.v1.SubjectB\x06\xbaH\x03\xc8\x01\x01R\asubject\"\xd6\x05\n" +
+ "\x1aPermissionBulkCheckRequest\x12\xa7\x02\n" +
+ "\ttenant_id\x18\x01 \x01(\tB\x88\x02\x92A\xd9\x012\xd6\x01Identifier of the tenant, if you are not using multi-tenancy (have only one tenant) use pre-inserted tenant t1 for this field. Required, and must match the pattern \\“[a-zA-Z0-9-,]+\\“, max 64 bytes.\xbaH(r&(\x80\x012!^([a-zA-Z0-9_\\-@\\.:+]{1,128}|\\*)$R\ttenant_id\x12K\n" +
+ "\bmetadata\x18\x02 \x01(\v2'.base.v1.PermissionCheckRequestMetadataB\x06\xbaH\x03\xc8\x01\x01R\bmetadata\x12I\n" +
"\x05items\x18\x03 \x03(\v2'.base.v1.PermissionBulkCheckRequestItemB\n" +
- "\xfaB\a\x92\x01\x04\b\x01\x10dR\x05items\x12\xc4\x01\n" +
+ "\xbaH\a\x92\x01\x04\b\x01\x10dR\x05items\x12\xc4\x01\n" +
"\acontext\x18\x04 \x01(\v2\x10.base.v1.ContextB\x97\x01\x92A\x93\x012\x90\x01Contextual data that can be dynamically added to permission check requests. See details on [Contextual Data](../../operations/contextual-tuples)R\acontext\x12/\n" +
"\targuments\x18\x05 \x03(\v2\x11.base.v1.ArgumentR\targuments\"Y\n" +
"\x1bPermissionBulkCheckResponse\x12:\n" +
- "\aresults\x18\x01 \x03(\v2 .base.v1.PermissionCheckResponseR\aresults\"\xe5\x04\n" +
- "\x17PermissionExpandRequest\x12\xaa\x02\n" +
- "\ttenant_id\x18\x01 \x01(\tB\x8b\x02\x92A\xd9\x012\xd6\x01Identifier of the tenant, if you are not using multi-tenancy (have only one tenant) use pre-inserted tenant t1 for this field. Required, and must match the pattern \\“[a-zA-Z0-9-,]+\\“, max 64 bytes.\xfaB+r)(\x80\x012!^([a-zA-Z0-9_\\-@\\.:+]{1,128}|\\*)$\xd0\x01\x00R\ttenant_id\x12N\n" +
- "\bmetadata\x18\x02 \x01(\v2(.base.v1.PermissionExpandRequestMetadataB\b\xfaB\x05\x8a\x01\x02\x10\x01R\bmetadata\x121\n" +
- "\x06entity\x18\x03 \x01(\v2\x0f.base.v1.EntityB\b\xfaB\x05\x8a\x01\x02\x10\x01R\x06entity\x12=\n" +
+ "\aresults\x18\x01 \x03(\v2 .base.v1.PermissionCheckResponseR\aresults\"\xde\x04\n" +
+ "\x17PermissionExpandRequest\x12\xa7\x02\n" +
+ "\ttenant_id\x18\x01 \x01(\tB\x88\x02\x92A\xd9\x012\xd6\x01Identifier of the tenant, if you are not using multi-tenancy (have only one tenant) use pre-inserted tenant t1 for this field. Required, and must match the pattern \\“[a-zA-Z0-9-,]+\\“, max 64 bytes.\xbaH(r&(\x80\x012!^([a-zA-Z0-9_\\-@\\.:+]{1,128}|\\*)$R\ttenant_id\x12L\n" +
+ "\bmetadata\x18\x02 \x01(\v2(.base.v1.PermissionExpandRequestMetadataB\x06\xbaH\x03\xc8\x01\x01R\bmetadata\x12/\n" +
+ "\x06entity\x18\x03 \x01(\v2\x0f.base.v1.EntityB\x06\xbaH\x03\xc8\x01\x01R\x06entity\x12=\n" +
"\n" +
- "permission\x18\x04 \x01(\tB\x1d\xfaB\x1ar\x18(@2\x11^[a-zA-Z_]{1,64}$\xd0\x01\x01R\n" +
+ "permission\x18\x04 \x01(\tB\x1d\xbaH\x1a\xd8\x01\x01r\x15(@2\x11^[a-zA-Z_]{1,64}$R\n" +
"permission\x12*\n" +
"\acontext\x18\x05 \x01(\v2\x10.base.v1.ContextR\acontext\x12/\n" +
"\targuments\x18\x06 \x03(\v2\x11.base.v1.ArgumentR\targuments\"\xd6\x01\n" +
@@ -3950,19 +3950,20 @@ const file_base_v1_service_proto_rawDesc = "" +
"snap_token\x18\x02 \x01(\tBj\x92Ag2eThe snap token to avoid stale cache, see more details on [Snap Tokens](../../operations/snap-tokens).R\n" +
"snap_token\"?\n" +
"\x18PermissionExpandResponse\x12#\n" +
- "\x04tree\x18\x01 \x01(\v2\x0f.base.v1.ExpandR\x04tree\"\x81\a\n" +
- "\x1dPermissionLookupEntityRequest\x12\xaa\x02\n" +
- "\ttenant_id\x18\x01 \x01(\tB\x8b\x02\x92A\xd9\x012\xd6\x01Identifier of the tenant, if you are not using multi-tenancy (have only one tenant) use pre-inserted tenant t1 for this field. Required, and must match the pattern \\“[a-zA-Z0-9-,]+\\“, max 64 bytes.\xfaB+r)(\x80\x012!^([a-zA-Z0-9_\\-@\\.:+]{1,128}|\\*)$\xd0\x01\x00R\ttenant_id\x12T\n" +
- "\bmetadata\x18\x02 \x01(\v2..base.v1.PermissionLookupEntityRequestMetadataB\b\xfaB\x05\x8a\x01\x02\x10\x01R\bmetadata\x12?\n" +
- "\ventity_type\x18\x03 \x01(\tB\x1d\xfaB\x1ar\x18(@2\x11^[a-zA-Z_]{1,64}$\xd0\x01\x00R\ventity_type\x12=\n" +
+ "\x04tree\x18\x01 \x01(\v2\x0f.base.v1.ExpandR\x04tree\"\xf5\x06\n" +
+ "\x1dPermissionLookupEntityRequest\x12\xa7\x02\n" +
+ "\ttenant_id\x18\x01 \x01(\tB\x88\x02\x92A\xd9\x012\xd6\x01Identifier of the tenant, if you are not using multi-tenancy (have only one tenant) use pre-inserted tenant t1 for this field. Required, and must match the pattern \\“[a-zA-Z0-9-,]+\\“, max 64 bytes.\xbaH(r&(\x80\x012!^([a-zA-Z0-9_\\-@\\.:+]{1,128}|\\*)$R\ttenant_id\x12R\n" +
+ "\bmetadata\x18\x02 \x01(\v2..base.v1.PermissionLookupEntityRequestMetadataB\x06\xbaH\x03\xc8\x01\x01R\bmetadata\x12<\n" +
+ "\ventity_type\x18\x03 \x01(\tB\x1a\xbaH\x17r\x15(@2\x11^[a-zA-Z_]{1,64}$R\ventity_type\x12:\n" +
"\n" +
- "permission\x18\x04 \x01(\tB\x1d\xfaB\x1ar\x18(@2\x11^[a-zA-Z_]{1,64}$\xd0\x01\x00R\n" +
- "permission\x124\n" +
- "\asubject\x18\x05 \x01(\v2\x10.base.v1.SubjectB\b\xfaB\x05\x8a\x01\x02\x10\x01R\asubject\x12*\n" +
+ "permission\x18\x04 \x01(\tB\x1a\xbaH\x17r\x15(@2\x11^[a-zA-Z_]{1,64}$R\n" +
+ "permission\x122\n" +
+ "\asubject\x18\x05 \x01(\v2\x10.base.v1.SubjectB\x06\xbaH\x03\xc8\x01\x01R\asubject\x12*\n" +
"\acontext\x18\x06 \x01(\v2\x10.base.v1.ContextR\acontext\x12G\n" +
- "\x05scope\x18\a \x03(\v21.base.v1.PermissionLookupEntityRequest.ScopeEntryR\x05scope\x12'\n" +
- "\tpage_size\x18\b \x01(\rB\t\xfaB\x06*\x04(\x01@\x01R\tpage_size\x124\n" +
- "\x10continuous_token\x18\t \x01(\tB\b\xfaB\x05r\x03\xd0\x01\x01R\x10continuous_token\x1aS\n" +
+ "\x05scope\x18\a \x03(\v21.base.v1.PermissionLookupEntityRequest.ScopeEntryR\x05scope\x12(\n" +
+ "\tpage_size\x18\b \x01(\rB\n" +
+ "\xbaH\a\xd8\x01\x01*\x02(\x01R\tpage_size\x124\n" +
+ "\x10continuous_token\x18\t \x01(\tB\b\xbaH\x05\xd8\x01\x01r\x00R\x10continuous_token\x1aS\n" +
"\n" +
"ScopeEntry\x12\x10\n" +
"\x03key\x18\x01 \x01(\tR\x03key\x12/\n" +
@@ -3972,7 +3973,7 @@ const file_base_v1_service_proto_rawDesc = "" +
"\n" +
"snap_token\x18\x02 \x01(\tBj\x92Ag2eThe snap token to avoid stale cache, see more details on [Snap Tokens](../../operations/snap-tokens).R\n" +
"snap_token\x12]\n" +
- "\x05depth\x18\x03 \x01(\x05BG\x92A=2;Query limit when if recursive database queries got in loop.\xfaB\x04\x1a\x02(\x03R\x05depth\"l\n" +
+ "\x05depth\x18\x03 \x01(\x05BG\x92A=2;Query limit when if recursive database queries got in loop.\xbaH\x04\x1a\x02(\x03R\x05depth\"l\n" +
"\x1ePermissionLookupEntityResponse\x12\x1e\n" +
"\n" +
"entity_ids\x18\x01 \x03(\tR\n" +
@@ -3980,15 +3981,15 @@ const file_base_v1_service_proto_rawDesc = "" +
"\x10continuous_token\x18\x02 \x01(\tR\x10continuous_token\"p\n" +
"$PermissionLookupEntityStreamResponse\x12\x1c\n" +
"\tentity_id\x18\x01 \x01(\tR\tentity_id\x12*\n" +
- "\x10continuous_token\x18\x02 \x01(\tR\x10continuous_token\"\xe9\x05\n" +
- "\x1dPermissionEntityFilterRequest\x12\xaa\x02\n" +
- "\ttenant_id\x18\x01 \x01(\tB\x8b\x02\x92A\xd9\x012\xd6\x01Identifier of the tenant, if you are not using multi-tenancy (have only one tenant) use pre-inserted tenant t1 for this field. Required, and must match the pattern \\“[a-zA-Z0-9-,]+\\“, max 64 bytes.\xfaB+r)(\x80\x012!^([a-zA-Z0-9_\\-@\\.:+]{1,128}|\\*)$\xd0\x01\x00R\ttenant_id\x12T\n" +
- "\bmetadata\x18\x02 \x01(\v2..base.v1.PermissionEntityFilterRequestMetadataB\b\xfaB\x05\x8a\x01\x02\x10\x01R\bmetadata\x12-\n" +
+ "\x10continuous_token\x18\x02 \x01(\tR\x10continuous_token\"\xe4\x05\n" +
+ "\x1dPermissionEntityFilterRequest\x12\xa7\x02\n" +
+ "\ttenant_id\x18\x01 \x01(\tB\x88\x02\x92A\xd9\x012\xd6\x01Identifier of the tenant, if you are not using multi-tenancy (have only one tenant) use pre-inserted tenant t1 for this field. Required, and must match the pattern \\“[a-zA-Z0-9-,]+\\“, max 64 bytes.\xbaH(r&(\x80\x012!^([a-zA-Z0-9_\\-@\\.:+]{1,128}|\\*)$R\ttenant_id\x12R\n" +
+ "\bmetadata\x18\x02 \x01(\v2..base.v1.PermissionEntityFilterRequestMetadataB\x06\xbaH\x03\xc8\x01\x01R\bmetadata\x12-\n" +
"\bentrance\x18\x03 \x01(\v2\x11.base.v1.EntranceR\bentrance\x12*\n" +
"\asubject\x18\x04 \x01(\v2\x10.base.v1.SubjectR\asubject\x12*\n" +
"\acontext\x18\x05 \x01(\v2\x10.base.v1.ContextR\acontext\x12G\n" +
"\x05scope\x18\x06 \x03(\v21.base.v1.PermissionEntityFilterRequest.ScopeEntryR\x05scope\x12 \n" +
- "\x06cursor\x18\a \x01(\tB\b\xfaB\x05r\x03\xd0\x01\x01R\x06cursor\x1aS\n" +
+ "\x06cursor\x18\a \x01(\tB\b\xbaH\x05\xd8\x01\x01r\x00R\x06cursor\x1aS\n" +
"\n" +
"ScopeEntry\x12\x10\n" +
"\x03key\x18\x01 \x01(\tR\x03key\x12/\n" +
@@ -3998,33 +3999,34 @@ const file_base_v1_service_proto_rawDesc = "" +
"\n" +
"snap_token\x18\x02 \x01(\tBj\x92Ag2eThe snap token to avoid stale cache, see more details on [Snap Tokens](../../operations/snap-tokens).R\n" +
"snap_token\x12]\n" +
- "\x05depth\x18\x03 \x01(\x05BG\x92A=2;Query limit when if recursive database queries got in loop.\xfaB\x04\x1a\x02(\x03R\x05depth\"\xa6\x06\n" +
- "\x1ePermissionLookupSubjectRequest\x12\xaa\x02\n" +
- "\ttenant_id\x18\x01 \x01(\tB\x8b\x02\x92A\xd9\x012\xd6\x01Identifier of the tenant, if you are not using multi-tenancy (have only one tenant) use pre-inserted tenant t1 for this field. Required, and must match the pattern \\“[a-zA-Z0-9-,]+\\“, max 64 bytes.\xfaB+r)(\x80\x012!^([a-zA-Z0-9_\\-@\\.:+]{1,128}|\\*)$\xd0\x01\x00R\ttenant_id\x12U\n" +
- "\bmetadata\x18\x02 \x01(\v2/.base.v1.PermissionLookupSubjectRequestMetadataB\b\xfaB\x05\x8a\x01\x02\x10\x01R\bmetadata\x121\n" +
- "\x06entity\x18\x03 \x01(\v2\x0f.base.v1.EntityB\b\xfaB\x05\x8a\x01\x02\x10\x01R\x06entity\x12=\n" +
+ "\x05depth\x18\x03 \x01(\x05BG\x92A=2;Query limit when if recursive database queries got in loop.\xbaH\x04\x1a\x02(\x03R\x05depth\"\x9b\x06\n" +
+ "\x1ePermissionLookupSubjectRequest\x12\xa7\x02\n" +
+ "\ttenant_id\x18\x01 \x01(\tB\x88\x02\x92A\xd9\x012\xd6\x01Identifier of the tenant, if you are not using multi-tenancy (have only one tenant) use pre-inserted tenant t1 for this field. Required, and must match the pattern \\“[a-zA-Z0-9-,]+\\“, max 64 bytes.\xbaH(r&(\x80\x012!^([a-zA-Z0-9_\\-@\\.:+]{1,128}|\\*)$R\ttenant_id\x12S\n" +
+ "\bmetadata\x18\x02 \x01(\v2/.base.v1.PermissionLookupSubjectRequestMetadataB\x06\xbaH\x03\xc8\x01\x01R\bmetadata\x12/\n" +
+ "\x06entity\x18\x03 \x01(\v2\x0f.base.v1.EntityB\x06\xbaH\x03\xc8\x01\x01R\x06entity\x12:\n" +
"\n" +
- "permission\x18\x04 \x01(\tB\x1d\xfaB\x1ar\x18(@2\x11^[a-zA-Z_]{1,64}$\xd0\x01\x00R\n" +
- "permission\x12R\n" +
- "\x11subject_reference\x18\x05 \x01(\v2\x1a.base.v1.RelationReferenceB\b\xfaB\x05\x8a\x01\x02\x10\x01R\x11subject_reference\x12*\n" +
+ "permission\x18\x04 \x01(\tB\x1a\xbaH\x17r\x15(@2\x11^[a-zA-Z_]{1,64}$R\n" +
+ "permission\x12P\n" +
+ "\x11subject_reference\x18\x05 \x01(\v2\x1a.base.v1.RelationReferenceB\x06\xbaH\x03\xc8\x01\x01R\x11subject_reference\x12*\n" +
"\acontext\x18\x06 \x01(\v2\x10.base.v1.ContextR\acontext\x12/\n" +
- "\targuments\x18\a \x03(\v2\x11.base.v1.ArgumentR\targuments\x12'\n" +
- "\tpage_size\x18\b \x01(\rB\t\xfaB\x06*\x04(\x01@\x01R\tpage_size\x124\n" +
- "\x10continuous_token\x18\t \x01(\tB\b\xfaB\x05r\x03\xd0\x01\x01R\x10continuous_token\"\xbc\x02\n" +
+ "\targuments\x18\a \x03(\v2\x11.base.v1.ArgumentR\targuments\x12(\n" +
+ "\tpage_size\x18\b \x01(\rB\n" +
+ "\xbaH\a\xd8\x01\x01*\x02(\x01R\tpage_size\x124\n" +
+ "\x10continuous_token\x18\t \x01(\tB\b\xbaH\x05\xd8\x01\x01r\x00R\x10continuous_token\"\xbc\x02\n" +
"&PermissionLookupSubjectRequestMetadata\x12&\n" +
"\x0eschema_version\x18\x01 \x01(\tR\x0eschema_version\x12\x8a\x01\n" +
"\n" +
"snap_token\x18\x02 \x01(\tBj\x92Ag2eThe snap token to avoid stale cache, see more details on [Snap Tokens](../../operations/snap-tokens).R\n" +
"snap_token\x12]\n" +
- "\x05depth\x18\x03 \x01(\x05BG\x92A=2;Query limit when if recursive database queries got in loop.\xfaB\x04\x1a\x02(\x03R\x05depth\"o\n" +
+ "\x05depth\x18\x03 \x01(\x05BG\x92A=2;Query limit when if recursive database queries got in loop.\xbaH\x04\x1a\x02(\x03R\x05depth\"o\n" +
"\x1fPermissionLookupSubjectResponse\x12 \n" +
"\vsubject_ids\x18\x01 \x03(\tR\vsubject_ids\x12*\n" +
- "\x10continuous_token\x18\x02 \x01(\tR\x10continuous_token\"\xc1\x04\n" +
- "\"PermissionSubjectPermissionRequest\x12\xaa\x02\n" +
- "\ttenant_id\x18\x01 \x01(\tB\x8b\x02\x92A\xd9\x012\xd6\x01Identifier of the tenant, if you are not using multi-tenancy (have only one tenant) use pre-inserted tenant t1 for this field. Required, and must match the pattern \\“[a-zA-Z0-9-,]+\\“, max 64 bytes.\xfaB+r)(\x80\x012!^([a-zA-Z0-9_\\-@\\.:+]{1,128}|\\*)$\xd0\x01\x00R\ttenant_id\x12Y\n" +
- "\bmetadata\x18\x02 \x01(\v23.base.v1.PermissionSubjectPermissionRequestMetadataB\b\xfaB\x05\x8a\x01\x02\x10\x01R\bmetadata\x121\n" +
- "\x06entity\x18\x03 \x01(\v2\x0f.base.v1.EntityB\b\xfaB\x05\x8a\x01\x02\x10\x01R\x06entity\x124\n" +
- "\asubject\x18\x04 \x01(\v2\x10.base.v1.SubjectB\b\xfaB\x05\x8a\x01\x02\x10\x01R\asubject\x12*\n" +
+ "\x10continuous_token\x18\x02 \x01(\tR\x10continuous_token\"\xb8\x04\n" +
+ "\"PermissionSubjectPermissionRequest\x12\xa7\x02\n" +
+ "\ttenant_id\x18\x01 \x01(\tB\x88\x02\x92A\xd9\x012\xd6\x01Identifier of the tenant, if you are not using multi-tenancy (have only one tenant) use pre-inserted tenant t1 for this field. Required, and must match the pattern \\“[a-zA-Z0-9-,]+\\“, max 64 bytes.\xbaH(r&(\x80\x012!^([a-zA-Z0-9_\\-@\\.:+]{1,128}|\\*)$R\ttenant_id\x12W\n" +
+ "\bmetadata\x18\x02 \x01(\v23.base.v1.PermissionSubjectPermissionRequestMetadataB\x06\xbaH\x03\xc8\x01\x01R\bmetadata\x12/\n" +
+ "\x06entity\x18\x03 \x01(\v2\x0f.base.v1.EntityB\x06\xbaH\x03\xc8\x01\x01R\x06entity\x122\n" +
+ "\asubject\x18\x04 \x01(\v2\x10.base.v1.SubjectB\x06\xbaH\x03\xc8\x01\x01R\asubject\x12*\n" +
"\acontext\x18\x05 \x01(\v2\x10.base.v1.ContextR\acontext\"\xea\x02\n" +
"*PermissionSubjectPermissionRequestMetadata\x12&\n" +
"\x0eschema_version\x18\x01 \x01(\tR\x0eschema_version\x12\x8a\x01\n" +
@@ -4032,27 +4034,27 @@ const file_base_v1_service_proto_rawDesc = "" +
"snap_token\x18\x02 \x01(\tBj\x92Ag2eThe snap token to avoid stale cache, see more details on [Snap Tokens](../../operations/snap-tokens).R\n" +
"snap_token\x12(\n" +
"\x0fonly_permission\x18\x03 \x01(\bR\x0fonly_permission\x12]\n" +
- "\x05depth\x18\x04 \x01(\x05BG\x92A=2;Query limit when if recursive database queries got in loop.\xfaB\x04\x1a\x02(\x03R\x05depth\"\xcc\x01\n" +
+ "\x05depth\x18\x04 \x01(\x05BG\x92A=2;Query limit when if recursive database queries got in loop.\xbaH\x04\x1a\x02(\x03R\x05depth\"\xcc\x01\n" +
"#PermissionSubjectPermissionResponse\x12S\n" +
"\aresults\x18\x01 \x03(\v29.base.v1.PermissionSubjectPermissionResponse.ResultsEntryR\aresults\x1aP\n" +
"\fResultsEntry\x12\x10\n" +
"\x03key\x18\x01 \x01(\tR\x03key\x12*\n" +
- "\x05value\x18\x02 \x01(\x0e2\x14.base.v1.CheckResultR\x05value:\x028\x01\"\xc8\x03\n" +
- "\fWatchRequest\x12\xaa\x02\n" +
- "\ttenant_id\x18\x01 \x01(\tB\x8b\x02\x92A\xd9\x012\xd6\x01Identifier of the tenant, if you are not using multi-tenancy (have only one tenant) use pre-inserted tenant t1 for this field. Required, and must match the pattern \\“[a-zA-Z0-9-,]+\\“, max 64 bytes.\xfaB+r)(\x80\x012!^([a-zA-Z0-9_\\-@\\.:+]{1,128}|\\*)$\xd0\x01\x00R\ttenant_id\x12\x8a\x01\n" +
+ "\x05value\x18\x02 \x01(\x0e2\x14.base.v1.CheckResultR\x05value:\x028\x01\"\xc5\x03\n" +
+ "\fWatchRequest\x12\xa7\x02\n" +
+ "\ttenant_id\x18\x01 \x01(\tB\x88\x02\x92A\xd9\x012\xd6\x01Identifier of the tenant, if you are not using multi-tenancy (have only one tenant) use pre-inserted tenant t1 for this field. Required, and must match the pattern \\“[a-zA-Z0-9-,]+\\“, max 64 bytes.\xbaH(r&(\x80\x012!^([a-zA-Z0-9_\\-@\\.:+]{1,128}|\\*)$R\ttenant_id\x12\x8a\x01\n" +
"\n" +
"snap_token\x18\x02 \x01(\tBj\x92Ag2eThe snap token to avoid stale cache, see more details on [Snap Tokens](../../operations/snap-tokens).R\n" +
"snap_token\"?\n" +
"\rWatchResponse\x12.\n" +
- "\achanges\x18\x01 \x01(\v2\x14.base.v1.DataChangesR\achanges\"\xd9\x02\n" +
- "\x12SchemaWriteRequest\x12\xaa\x02\n" +
- "\ttenant_id\x18\x01 \x01(\tB\x8b\x02\x92A\xd9\x012\xd6\x01Identifier of the tenant, if you are not using multi-tenancy (have only one tenant) use pre-inserted tenant t1 for this field. Required, and must match the pattern \\“[a-zA-Z0-9-,]+\\“, max 64 bytes.\xfaB+r)(\x80\x012!^([a-zA-Z0-9_\\-@\\.:+]{1,128}|\\*)$\xd0\x01\x00R\ttenant_id\x12\x16\n" +
+ "\achanges\x18\x01 \x01(\v2\x14.base.v1.DataChangesR\achanges\"\xd6\x02\n" +
+ "\x12SchemaWriteRequest\x12\xa7\x02\n" +
+ "\ttenant_id\x18\x01 \x01(\tB\x88\x02\x92A\xd9\x012\xd6\x01Identifier of the tenant, if you are not using multi-tenancy (have only one tenant) use pre-inserted tenant t1 for this field. Required, and must match the pattern \\“[a-zA-Z0-9-,]+\\“, max 64 bytes.\xbaH(r&(\x80\x012!^([a-zA-Z0-9_\\-@\\.:+]{1,128}|\\*)$R\ttenant_id\x12\x16\n" +
"\x06schema\x18\x02 \x01(\tR\x06schema\"=\n" +
"\x13SchemaWriteResponse\x12&\n" +
- "\x0eschema_version\x18\x01 \x01(\tR\x0eschema_version\"\xd9\x02\n" +
- "\x19SchemaPartialWriteRequest\x12L\n" +
- "\ttenant_id\x18\x01 \x01(\tB.\xfaB+r)(\x80\x012!^([a-zA-Z0-9_\\-@\\.:+]{1,128}|\\*)$\xd0\x01\x00R\ttenant_id\x12P\n" +
- "\bmetadata\x18\x02 \x01(\v2*.base.v1.SchemaPartialWriteRequestMetadataB\b\xfaB\x05\x8a\x01\x02\x10\x01R\bmetadata\x12L\n" +
+ "\x0eschema_version\x18\x01 \x01(\tR\x0eschema_version\"\xd4\x02\n" +
+ "\x19SchemaPartialWriteRequest\x12I\n" +
+ "\ttenant_id\x18\x01 \x01(\tB+\xbaH(r&(\x80\x012!^([a-zA-Z0-9_\\-@\\.:+]{1,128}|\\*)$R\ttenant_id\x12N\n" +
+ "\bmetadata\x18\x02 \x01(\v2*.base.v1.SchemaPartialWriteRequestMetadataB\x06\xbaH\x03\xc8\x01\x01R\bmetadata\x12L\n" +
"\bpartials\x18\x03 \x03(\v20.base.v1.SchemaPartialWriteRequest.PartialsEntryR\bpartials\x1aN\n" +
"\rPartialsEntry\x12\x10\n" +
"\x03key\x18\x01 \x01(\tR\x03key\x12'\n" +
@@ -4060,18 +4062,19 @@ const file_base_v1_service_proto_rawDesc = "" +
"!SchemaPartialWriteRequestMetadata\x12&\n" +
"\x0eschema_version\x18\x01 \x01(\tR\x0eschema_version\"D\n" +
"\x1aSchemaPartialWriteResponse\x12&\n" +
- "\x0eschema_version\x18\x01 \x01(\tR\x0eschema_version\"\x8a\x03\n" +
- "\x11SchemaReadRequest\x12\xaa\x02\n" +
- "\ttenant_id\x18\x01 \x01(\tB\x8b\x02\x92A\xd9\x012\xd6\x01Identifier of the tenant, if you are not using multi-tenancy (have only one tenant) use pre-inserted tenant t1 for this field. Required, and must match the pattern \\“[a-zA-Z0-9-,]+\\“, max 64 bytes.\xfaB+r)(\x80\x012!^([a-zA-Z0-9_\\-@\\.:+]{1,128}|\\*)$\xd0\x01\x00R\ttenant_id\x12H\n" +
- "\bmetadata\x18\x02 \x01(\v2\".base.v1.SchemaReadRequestMetadataB\b\xfaB\x05\x8a\x01\x02\x10\x01R\bmetadata\"C\n" +
+ "\x0eschema_version\x18\x01 \x01(\tR\x0eschema_version\"\x85\x03\n" +
+ "\x11SchemaReadRequest\x12\xa7\x02\n" +
+ "\ttenant_id\x18\x01 \x01(\tB\x88\x02\x92A\xd9\x012\xd6\x01Identifier of the tenant, if you are not using multi-tenancy (have only one tenant) use pre-inserted tenant t1 for this field. Required, and must match the pattern \\“[a-zA-Z0-9-,]+\\“, max 64 bytes.\xbaH(r&(\x80\x012!^([a-zA-Z0-9_\\-@\\.:+]{1,128}|\\*)$R\ttenant_id\x12F\n" +
+ "\bmetadata\x18\x02 \x01(\v2\".base.v1.SchemaReadRequestMetadataB\x06\xbaH\x03\xc8\x01\x01R\bmetadata\"C\n" +
"\x19SchemaReadRequestMetadata\x12&\n" +
"\x0eschema_version\x18\x01 \x01(\tR\x0eschema_version\"G\n" +
"\x12SchemaReadResponse\x121\n" +
- "\x06schema\x18\x01 \x01(\v2\x19.base.v1.SchemaDefinitionR\x06schema\"\x9f\x03\n" +
- "\x11SchemaListRequest\x12\xaa\x02\n" +
- "\ttenant_id\x18\x01 \x01(\tB\x8b\x02\x92A\xd9\x012\xd6\x01Identifier of the tenant, if you are not using multi-tenancy (have only one tenant) use pre-inserted tenant t1 for this field. Required, and must match the pattern \\“[a-zA-Z0-9-,]+\\“, max 64 bytes.\xfaB+r)(\x80\x012!^([a-zA-Z0-9_\\-@\\.:+]{1,128}|\\*)$\xd0\x01\x00R\ttenant_id\x12'\n" +
- "\tpage_size\x18\x02 \x01(\rB\t\xfaB\x06*\x04(\x01@\x01R\tpage_size\x124\n" +
- "\x10continuous_token\x18\x03 \x01(\tB\b\xfaB\x05r\x03\xd0\x01\x01R\x10continuous_token\"\x83\x01\n" +
+ "\x06schema\x18\x01 \x01(\v2\x19.base.v1.SchemaDefinitionR\x06schema\"\x9d\x03\n" +
+ "\x11SchemaListRequest\x12\xa7\x02\n" +
+ "\ttenant_id\x18\x01 \x01(\tB\x88\x02\x92A\xd9\x012\xd6\x01Identifier of the tenant, if you are not using multi-tenancy (have only one tenant) use pre-inserted tenant t1 for this field. Required, and must match the pattern \\“[a-zA-Z0-9-,]+\\“, max 64 bytes.\xbaH(r&(\x80\x012!^([a-zA-Z0-9_\\-@\\.:+]{1,128}|\\*)$R\ttenant_id\x12(\n" +
+ "\tpage_size\x18\x02 \x01(\rB\n" +
+ "\xbaH\a\xd8\x01\x01*\x02(\x01R\tpage_size\x124\n" +
+ "\x10continuous_token\x18\x03 \x01(\tB\b\xbaH\x05\xd8\x01\x01r\x00R\x10continuous_token\"\x83\x01\n" +
"\x12SchemaListResponse\x12\x12\n" +
"\x04head\x18\x01 \x01(\tR\x04head\x12-\n" +
"\aschemas\x18\x02 \x03(\v2\x13.base.v1.SchemaListR\aschemas\x12*\n" +
@@ -4081,49 +4084,51 @@ const file_base_v1_service_proto_rawDesc = "" +
"\aversion\x18\x01 \x01(\tR\aversion\x12\x1e\n" +
"\n" +
"created_at\x18\x02 \x01(\tR\n" +
- "created_at\"\x86\x04\n" +
- "\x10DataWriteRequest\x12\xaa\x02\n" +
- "\ttenant_id\x18\x01 \x01(\tB\x8b\x02\x92A\xd9\x012\xd6\x01Identifier of the tenant, if you are not using multi-tenancy (have only one tenant) use pre-inserted tenant t1 for this field. Required, and must match the pattern \\“[a-zA-Z0-9-,]+\\“, max 64 bytes.\xfaB+r)(\x80\x012!^([a-zA-Z0-9_\\-@\\.:+]{1,128}|\\*)$\xd0\x01\x00R\ttenant_id\x12G\n" +
- "\bmetadata\x18\x02 \x01(\v2!.base.v1.DataWriteRequestMetadataB\b\xfaB\x05\x8a\x01\x02\x10\x01R\bmetadata\x127\n" +
- "\x06tuples\x18\x03 \x03(\v2\x0e.base.v1.TupleB\x0f\xfaB\f\x92\x01\t\b\x00\"\x05\x8a\x01\x02\x10\x01R\x06tuples\x12C\n" +
+ "created_at\"\xf3\x03\n" +
+ "\x10DataWriteRequest\x12\xa7\x02\n" +
+ "\ttenant_id\x18\x01 \x01(\tB\x88\x02\x92A\xd9\x012\xd6\x01Identifier of the tenant, if you are not using multi-tenancy (have only one tenant) use pre-inserted tenant t1 for this field. Required, and must match the pattern \\“[a-zA-Z0-9-,]+\\“, max 64 bytes.\xbaH(r&(\x80\x012!^([a-zA-Z0-9_\\-@\\.:+]{1,128}|\\*)$R\ttenant_id\x12E\n" +
+ "\bmetadata\x18\x02 \x01(\v2!.base.v1.DataWriteRequestMetadataB\x06\xbaH\x03\xc8\x01\x01R\bmetadata\x120\n" +
+ "\x06tuples\x18\x03 \x03(\v2\x0e.base.v1.TupleB\b\xbaH\x05\x92\x01\x02\b\x00R\x06tuples\x12<\n" +
"\n" +
- "attributes\x18\x04 \x03(\v2\x12.base.v1.AttributeB\x0f\xfaB\f\x92\x01\t\b\x00\"\x05\x8a\x01\x02\x10\x01R\n" +
+ "attributes\x18\x04 \x03(\v2\x12.base.v1.AttributeB\b\xbaH\x05\x92\x01\x02\b\x00R\n" +
"attributes\"B\n" +
"\x18DataWriteRequestMetadata\x12&\n" +
"\x0eschema_version\x18\x01 \x01(\tR\x0eschema_version\"\xa0\x01\n" +
"\x11DataWriteResponse\x12\x8a\x01\n" +
"\n" +
"snap_token\x18\x01 \x01(\tBj\x92Ag2eThe snap token to avoid stale cache, see more details on [Snap Tokens](../../operations/snap-tokens).R\n" +
- "snap_token\"\xd1\x03\n" +
- "\x18RelationshipWriteRequest\x12\xaa\x02\n" +
- "\ttenant_id\x18\x01 \x01(\tB\x8b\x02\x92A\xd9\x012\xd6\x01Identifier of the tenant, if you are not using multi-tenancy (have only one tenant) use pre-inserted tenant t1 for this field. Required, and must match the pattern \\“[a-zA-Z0-9-,]+\\“, max 64 bytes.\xfaB+r)(\x80\x012!^([a-zA-Z0-9_\\-@\\.:+]{1,128}|\\*)$\xd0\x01\x00R\ttenant_id\x12O\n" +
- "\bmetadata\x18\x02 \x01(\v2).base.v1.RelationshipWriteRequestMetadataB\b\xfaB\x05\x8a\x01\x02\x10\x01R\bmetadata\x127\n" +
- "\x06tuples\x18\x03 \x03(\v2\x0e.base.v1.TupleB\x0f\xfaB\f\x92\x01\t\b\x01\"\x05\x8a\x01\x02\x10\x01R\x06tuples\"J\n" +
+ "snap_token\"\xc5\x03\n" +
+ "\x18RelationshipWriteRequest\x12\xa7\x02\n" +
+ "\ttenant_id\x18\x01 \x01(\tB\x88\x02\x92A\xd9\x012\xd6\x01Identifier of the tenant, if you are not using multi-tenancy (have only one tenant) use pre-inserted tenant t1 for this field. Required, and must match the pattern \\“[a-zA-Z0-9-,]+\\“, max 64 bytes.\xbaH(r&(\x80\x012!^([a-zA-Z0-9_\\-@\\.:+]{1,128}|\\*)$R\ttenant_id\x12M\n" +
+ "\bmetadata\x18\x02 \x01(\v2).base.v1.RelationshipWriteRequestMetadataB\x06\xbaH\x03\xc8\x01\x01R\bmetadata\x120\n" +
+ "\x06tuples\x18\x03 \x03(\v2\x0e.base.v1.TupleB\b\xbaH\x05\x92\x01\x02\b\x01R\x06tuples\"J\n" +
" RelationshipWriteRequestMetadata\x12&\n" +
"\x0eschema_version\x18\x01 \x01(\tR\x0eschema_version\"\xa7\x01\n" +
"\x19RelationshipWriteResponse\x12\x89\x01\n" +
"\n" +
"snap_token\x18\x01 \x01(\tBi\x92Af2dThe snap token to avoid stale cache, see more details on [Snap Tokens](../../operations/snap-tokens)R\n" +
- "snap_token\"\xad\x04\n" +
- "\x17RelationshipReadRequest\x12\xaa\x02\n" +
- "\ttenant_id\x18\x01 \x01(\tB\x8b\x02\x92A\xd9\x012\xd6\x01Identifier of the tenant, if you are not using multi-tenancy (have only one tenant) use pre-inserted tenant t1 for this field. Required, and must match the pattern \\“[a-zA-Z0-9-,]+\\“, max 64 bytes.\xfaB+r)(\x80\x012!^([a-zA-Z0-9_\\-@\\.:+]{1,128}|\\*)$\xd0\x01\x00R\ttenant_id\x12N\n" +
- "\bmetadata\x18\x02 \x01(\v2(.base.v1.RelationshipReadRequestMetadataB\b\xfaB\x05\x8a\x01\x02\x10\x01R\bmetadata\x126\n" +
- "\x06filter\x18\x03 \x01(\v2\x14.base.v1.TupleFilterB\b\xfaB\x05\x8a\x01\x02\x10\x01R\x06filter\x12'\n" +
- "\tpage_size\x18\x04 \x01(\rB\t\xfaB\x06*\x04(\x01@\x01R\tpage_size\x124\n" +
- "\x10continuous_token\x18\x05 \x01(\tB\b\xfaB\x05r\x03\xd0\x01\x01R\x10continuous_token\"\xad\x01\n" +
+ "snap_token\"\xa7\x04\n" +
+ "\x17RelationshipReadRequest\x12\xa7\x02\n" +
+ "\ttenant_id\x18\x01 \x01(\tB\x88\x02\x92A\xd9\x012\xd6\x01Identifier of the tenant, if you are not using multi-tenancy (have only one tenant) use pre-inserted tenant t1 for this field. Required, and must match the pattern \\“[a-zA-Z0-9-,]+\\“, max 64 bytes.\xbaH(r&(\x80\x012!^([a-zA-Z0-9_\\-@\\.:+]{1,128}|\\*)$R\ttenant_id\x12L\n" +
+ "\bmetadata\x18\x02 \x01(\v2(.base.v1.RelationshipReadRequestMetadataB\x06\xbaH\x03\xc8\x01\x01R\bmetadata\x124\n" +
+ "\x06filter\x18\x03 \x01(\v2\x14.base.v1.TupleFilterB\x06\xbaH\x03\xc8\x01\x01R\x06filter\x12(\n" +
+ "\tpage_size\x18\x04 \x01(\rB\n" +
+ "\xbaH\a\xd8\x01\x01*\x02(\x01R\tpage_size\x124\n" +
+ "\x10continuous_token\x18\x05 \x01(\tB\b\xbaH\x05\xd8\x01\x01r\x00R\x10continuous_token\"\xad\x01\n" +
"\x1fRelationshipReadRequestMetadata\x12\x89\x01\n" +
"\n" +
"snap_token\x18\x01 \x01(\tBi\x92Af2dThe snap token to avoid stale cache, see more details on [Snap Tokens](../../operations/snap-tokens)R\n" +
"snap_token\"n\n" +
"\x18RelationshipReadResponse\x12&\n" +
"\x06tuples\x18\x01 \x03(\v2\x0e.base.v1.TupleR\x06tuples\x12*\n" +
- "\x10continuous_token\x18\x02 \x01(\tR\x10continuous_token\"\xab\x04\n" +
- "\x14AttributeReadRequest\x12\xaa\x02\n" +
- "\ttenant_id\x18\x01 \x01(\tB\x8b\x02\x92A\xd9\x012\xd6\x01Identifier of the tenant, if you are not using multi-tenancy (have only one tenant) use pre-inserted tenant t1 for this field. Required, and must match the pattern \\“[a-zA-Z0-9-,]+\\“, max 64 bytes.\xfaB+r)(\x80\x012!^([a-zA-Z0-9_\\-@\\.:+]{1,128}|\\*)$\xd0\x01\x00R\ttenant_id\x12K\n" +
- "\bmetadata\x18\x02 \x01(\v2%.base.v1.AttributeReadRequestMetadataB\b\xfaB\x05\x8a\x01\x02\x10\x01R\bmetadata\x12:\n" +
- "\x06filter\x18\x03 \x01(\v2\x18.base.v1.AttributeFilterB\b\xfaB\x05\x8a\x01\x02\x10\x01R\x06filter\x12'\n" +
- "\tpage_size\x18\x04 \x01(\rB\t\xfaB\x06*\x04(\x01@\x01R\tpage_size\x124\n" +
- "\x10continuous_token\x18\x05 \x01(\tB\b\xfaB\x05r\x03\xd0\x01\x01R\x10continuous_token\"\xaa\x01\n" +
+ "\x10continuous_token\x18\x02 \x01(\tR\x10continuous_token\"\xa5\x04\n" +
+ "\x14AttributeReadRequest\x12\xa7\x02\n" +
+ "\ttenant_id\x18\x01 \x01(\tB\x88\x02\x92A\xd9\x012\xd6\x01Identifier of the tenant, if you are not using multi-tenancy (have only one tenant) use pre-inserted tenant t1 for this field. Required, and must match the pattern \\“[a-zA-Z0-9-,]+\\“, max 64 bytes.\xbaH(r&(\x80\x012!^([a-zA-Z0-9_\\-@\\.:+]{1,128}|\\*)$R\ttenant_id\x12I\n" +
+ "\bmetadata\x18\x02 \x01(\v2%.base.v1.AttributeReadRequestMetadataB\x06\xbaH\x03\xc8\x01\x01R\bmetadata\x128\n" +
+ "\x06filter\x18\x03 \x01(\v2\x18.base.v1.AttributeFilterB\x06\xbaH\x03\xc8\x01\x01R\x06filter\x12(\n" +
+ "\tpage_size\x18\x04 \x01(\rB\n" +
+ "\xbaH\a\xd8\x01\x01*\x02(\x01R\tpage_size\x124\n" +
+ "\x10continuous_token\x18\x05 \x01(\tB\b\xbaH\x05\xd8\x01\x01r\x00R\x10continuous_token\"\xaa\x01\n" +
"\x1cAttributeReadRequestMetadata\x12\x89\x01\n" +
"\n" +
"snap_token\x18\x01 \x01(\tBi\x92Af2dThe snap token to avoid stale cache, see more details on [Snap Tokens](../../operations/snap-tokens)R\n" +
@@ -4132,24 +4137,24 @@ const file_base_v1_service_proto_rawDesc = "" +
"\n" +
"attributes\x18\x01 \x03(\v2\x12.base.v1.AttributeR\n" +
"attributes\x12*\n" +
- "\x10continuous_token\x18\x02 \x01(\tR\x10continuous_token\"\xd4\x03\n" +
- "\x11DataDeleteRequest\x12\xaa\x02\n" +
- "\ttenant_id\x18\x01 \x01(\tB\x8b\x02\x92A\xd9\x012\xd6\x01Identifier of the tenant, if you are not using multi-tenancy (have only one tenant) use pre-inserted tenant t1 for this field. Required, and must match the pattern \\“[a-zA-Z0-9-,]+\\“, max 64 bytes.\xfaB+r)(\x80\x012!^([a-zA-Z0-9_\\-@\\.:+]{1,128}|\\*)$\xd0\x01\x00R\ttenant_id\x12B\n" +
- "\ftuple_filter\x18\x02 \x01(\v2\x14.base.v1.TupleFilterB\b\xfaB\x05\x8a\x01\x02\x10\x01R\ftuple_filter\x12N\n" +
- "\x10attribute_filter\x18\x03 \x01(\v2\x18.base.v1.AttributeFilterB\b\xfaB\x05\x8a\x01\x02\x10\x01R\x10attribute_filter\"\xa0\x01\n" +
+ "\x10continuous_token\x18\x02 \x01(\tR\x10continuous_token\"\xcd\x03\n" +
+ "\x11DataDeleteRequest\x12\xa7\x02\n" +
+ "\ttenant_id\x18\x01 \x01(\tB\x88\x02\x92A\xd9\x012\xd6\x01Identifier of the tenant, if you are not using multi-tenancy (have only one tenant) use pre-inserted tenant t1 for this field. Required, and must match the pattern \\“[a-zA-Z0-9-,]+\\“, max 64 bytes.\xbaH(r&(\x80\x012!^([a-zA-Z0-9_\\-@\\.:+]{1,128}|\\*)$R\ttenant_id\x12@\n" +
+ "\ftuple_filter\x18\x02 \x01(\v2\x14.base.v1.TupleFilterB\x06\xbaH\x03\xc8\x01\x01R\ftuple_filter\x12L\n" +
+ "\x10attribute_filter\x18\x03 \x01(\v2\x18.base.v1.AttributeFilterB\x06\xbaH\x03\xc8\x01\x01R\x10attribute_filter\"\xa0\x01\n" +
"\x12DataDeleteResponse\x12\x89\x01\n" +
"\n" +
"snap_token\x18\x01 \x01(\tBi\x92Af2dThe snap token to avoid stale cache, see more details on [Snap Tokens](../../operations/snap-tokens)R\n" +
- "snap_token\"\xf6\x02\n" +
- "\x19RelationshipDeleteRequest\x12\xaa\x02\n" +
- "\ttenant_id\x18\x01 \x01(\tB\x8b\x02\x92A\xd9\x012\xd6\x01Identifier of the tenant, if you are not using multi-tenancy (have only one tenant) use pre-inserted tenant t1 for this field. Required, and must match the pattern \\“[a-zA-Z0-9-,]+\\“, max 64 bytes.\xfaB+r)(\x80\x012!^([a-zA-Z0-9_\\-@\\.:+]{1,128}|\\*)$\xd0\x01\x00R\ttenant_id\x12,\n" +
+ "snap_token\"\xf3\x02\n" +
+ "\x19RelationshipDeleteRequest\x12\xa7\x02\n" +
+ "\ttenant_id\x18\x01 \x01(\tB\x88\x02\x92A\xd9\x012\xd6\x01Identifier of the tenant, if you are not using multi-tenancy (have only one tenant) use pre-inserted tenant t1 for this field. Required, and must match the pattern \\“[a-zA-Z0-9-,]+\\“, max 64 bytes.\xbaH(r&(\x80\x012!^([a-zA-Z0-9_\\-@\\.:+]{1,128}|\\*)$R\ttenant_id\x12,\n" +
"\x06filter\x18\x02 \x01(\v2\x14.base.v1.TupleFilterR\x06filter\"\xa8\x01\n" +
"\x1aRelationshipDeleteResponse\x12\x89\x01\n" +
"\n" +
"snap_token\x18\x01 \x01(\tBi\x92Af2dThe snap token to avoid stale cache, see more details on [Snap Tokens](../../operations/snap-tokens)R\n" +
- "snap_token\"\xd9\x03\n" +
- "\x10BundleRunRequest\x12\xaa\x02\n" +
- "\ttenant_id\x18\x01 \x01(\tB\x8b\x02\x92A\xd9\x012\xd6\x01Identifier of the tenant, if you are not using multi-tenancy (have only one tenant) use pre-inserted tenant t1 for this field. Required, and must match the pattern \\“[a-zA-Z0-9-,]+\\“, max 64 bytes.\xfaB+r)(\x80\x012!^([a-zA-Z0-9_\\-@\\.:+]{1,128}|\\*)$\xd0\x01\x00R\ttenant_id\x12\x12\n" +
+ "snap_token\"\xd6\x03\n" +
+ "\x10BundleRunRequest\x12\xa7\x02\n" +
+ "\ttenant_id\x18\x01 \x01(\tB\x88\x02\x92A\xd9\x012\xd6\x01Identifier of the tenant, if you are not using multi-tenancy (have only one tenant) use pre-inserted tenant t1 for this field. Required, and must match the pattern \\“[a-zA-Z0-9-,]+\\“, max 64 bytes.\xbaH(r&(\x80\x012!^([a-zA-Z0-9_\\-@\\.:+]{1,128}|\\*)$R\ttenant_id\x12\x12\n" +
"\x04name\x18\x02 \x01(\tR\x04name\x12F\n" +
"\targuments\x18\x03 \x03(\v2(.base.v1.BundleRunRequest.ArgumentsEntryR\targuments\x1a<\n" +
"\x0eArgumentsEntry\x12\x10\n" +
@@ -4158,35 +4163,35 @@ const file_base_v1_service_proto_rawDesc = "" +
"\x11BundleRunResponse\x12\x89\x01\n" +
"\n" +
"snap_token\x18\x01 \x01(\tBi\x92Af2dThe snap token to avoid stale cache, see more details on [Snap Tokens](../../operations/snap-tokens)R\n" +
- "snap_token\"\xf0\x02\n" +
- "\x12BundleWriteRequest\x12\xaa\x02\n" +
- "\ttenant_id\x18\x01 \x01(\tB\x8b\x02\x92A\xd9\x012\xd6\x01Identifier of the tenant, if you are not using multi-tenancy (have only one tenant) use pre-inserted tenant t1 for this field. Required, and must match the pattern \\“[a-zA-Z0-9-,]+\\“, max 64 bytes.\xfaB+r)(\x80\x012!^([a-zA-Z0-9_\\-@\\.:+]{1,128}|\\*)$\xd0\x01\x00R\ttenant_id\x12-\n" +
+ "snap_token\"\xed\x02\n" +
+ "\x12BundleWriteRequest\x12\xa7\x02\n" +
+ "\ttenant_id\x18\x01 \x01(\tB\x88\x02\x92A\xd9\x012\xd6\x01Identifier of the tenant, if you are not using multi-tenancy (have only one tenant) use pre-inserted tenant t1 for this field. Required, and must match the pattern \\“[a-zA-Z0-9-,]+\\“, max 64 bytes.\xbaH(r&(\x80\x012!^([a-zA-Z0-9_\\-@\\.:+]{1,128}|\\*)$R\ttenant_id\x12-\n" +
"\abundles\x18\x02 \x03(\v2\x13.base.v1.DataBundleR\abundles\"+\n" +
"\x13BundleWriteResponse\x12\x14\n" +
- "\x05names\x18\x01 \x03(\tR\x05names\"\xd4\x02\n" +
- "\x11BundleReadRequest\x12\xaa\x02\n" +
- "\ttenant_id\x18\x01 \x01(\tB\x8b\x02\x92A\xd9\x012\xd6\x01Identifier of the tenant, if you are not using multi-tenancy (have only one tenant) use pre-inserted tenant t1 for this field. Required, and must match the pattern \\“[a-zA-Z0-9-,]+\\“, max 64 bytes.\xfaB+r)(\x80\x012!^([a-zA-Z0-9_\\-@\\.:+]{1,128}|\\*)$\xd0\x01\x00R\ttenant_id\x12\x12\n" +
+ "\x05names\x18\x01 \x03(\tR\x05names\"\xd1\x02\n" +
+ "\x11BundleReadRequest\x12\xa7\x02\n" +
+ "\ttenant_id\x18\x01 \x01(\tB\x88\x02\x92A\xd9\x012\xd6\x01Identifier of the tenant, if you are not using multi-tenancy (have only one tenant) use pre-inserted tenant t1 for this field. Required, and must match the pattern \\“[a-zA-Z0-9-,]+\\“, max 64 bytes.\xbaH(r&(\x80\x012!^([a-zA-Z0-9_\\-@\\.:+]{1,128}|\\*)$R\ttenant_id\x12\x12\n" +
"\x04name\x18\x02 \x01(\tR\x04name\"A\n" +
"\x12BundleReadResponse\x12+\n" +
- "\x06bundle\x18\x01 \x01(\v2\x13.base.v1.DataBundleR\x06bundle\"\xd6\x02\n" +
- "\x13BundleDeleteRequest\x12\xaa\x02\n" +
- "\ttenant_id\x18\x01 \x01(\tB\x8b\x02\x92A\xd9\x012\xd6\x01Identifier of the tenant, if you are not using multi-tenancy (have only one tenant) use pre-inserted tenant t1 for this field. Required, and must match the pattern \\“[a-zA-Z0-9-,]+\\“, max 64 bytes.\xfaB+r)(\x80\x012!^([a-zA-Z0-9_\\-@\\.:+]{1,128}|\\*)$\xd0\x01\x00R\ttenant_id\x12\x12\n" +
+ "\x06bundle\x18\x01 \x01(\v2\x13.base.v1.DataBundleR\x06bundle\"\xd3\x02\n" +
+ "\x13BundleDeleteRequest\x12\xa7\x02\n" +
+ "\ttenant_id\x18\x01 \x01(\tB\x88\x02\x92A\xd9\x012\xd6\x01Identifier of the tenant, if you are not using multi-tenancy (have only one tenant) use pre-inserted tenant t1 for this field. Required, and must match the pattern \\“[a-zA-Z0-9-,]+\\“, max 64 bytes.\xbaH(r&(\x80\x012!^([a-zA-Z0-9_\\-@\\.:+]{1,128}|\\*)$R\ttenant_id\x12\x12\n" +
"\x04name\x18\x02 \x01(\tR\x04name\"*\n" +
"\x14BundleDeleteResponse\x12\x12\n" +
- "\x04name\x18\x01 \x01(\tR\x04name\"a\n" +
- "\x13TenantCreateRequest\x12*\n" +
- "\x02id\x18\x01 \x01(\tB\x1a\xfaB\x17r\x15(@2\x0e[a-zA-Z0-9-,]+\xd0\x01\x00R\x02id\x12\x1e\n" +
- "\x04name\x18\x02 \x01(\tB\n" +
- "\xfaB\ar\x05(@\xd0\x01\x00R\x04name\"?\n" +
+ "\x04name\x18\x01 \x01(\tR\x04name\"[\n" +
+ "\x13TenantCreateRequest\x12'\n" +
+ "\x02id\x18\x01 \x01(\tB\x17\xbaH\x14r\x12(@2\x0e[a-zA-Z0-9-,]+R\x02id\x12\x1b\n" +
+ "\x04name\x18\x02 \x01(\tB\a\xbaH\x04r\x02(@R\x04name\"?\n" +
"\x14TenantCreateResponse\x12'\n" +
- "\x06tenant\x18\x01 \x01(\v2\x0f.base.v1.TenantR\x06tenant\"/\n" +
- "\x13TenantDeleteRequest\x12\x18\n" +
- "\x02id\x18\x01 \x01(\tB\b\xfaB\x05r\x03\xd0\x01\x00R\x02id\"4\n" +
+ "\x06tenant\x18\x01 \x01(\v2\x0f.base.v1.TenantR\x06tenant\",\n" +
+ "\x13TenantDeleteRequest\x12\x15\n" +
+ "\x02id\x18\x01 \x01(\tB\x05\xbaH\x02r\x00R\x02id\"4\n" +
"\x14TenantDeleteResponse\x12\x1c\n" +
- "\ttenant_id\x18\x01 \x01(\tR\ttenant_id\"r\n" +
- "\x11TenantListRequest\x12'\n" +
- "\tpage_size\x18\x01 \x01(\rB\t\xfaB\x06*\x04(\x01@\x01R\tpage_size\x124\n" +
- "\x10continuous_token\x18\x02 \x01(\tB\b\xfaB\x05r\x03\xd0\x01\x01R\x10continuous_token\"k\n" +
+ "\ttenant_id\x18\x01 \x01(\tR\ttenant_id\"s\n" +
+ "\x11TenantListRequest\x12(\n" +
+ "\tpage_size\x18\x01 \x01(\rB\n" +
+ "\xbaH\a\xd8\x01\x01*\x02(\x01R\tpage_size\x124\n" +
+ "\x10continuous_token\x18\x02 \x01(\tB\b\xbaH\x05\xd8\x01\x01r\x00R\x10continuous_token\"k\n" +
"\x12TenantListResponse\x12)\n" +
"\atenants\x18\x01 \x03(\v2\x0f.base.v1.TenantR\atenants\x12*\n" +
"\x10continuous_token\x18\x02 \x01(\tR\x10continuous_token2\xafN\n" +
diff --git a/pkg/pb/base/v1/service_grpc.pb.go b/pkg/pb/base/v1/service_grpc.pb.go
index a2dd326db..e77922dbb 100644
--- a/pkg/pb/base/v1/service_grpc.pb.go
+++ b/pkg/pb/base/v1/service_grpc.pb.go
@@ -48,9 +48,12 @@ type PermissionClient interface {
Expand(ctx context.Context, in *PermissionExpandRequest, opts ...grpc.CallOption) (*PermissionExpandResponse, error)
// LookupEntity method receives a PermissionLookupEntityRequest and returns a PermissionLookupEntityResponse.
// It is used to retrieve an entity by its identifier.
+ // buf:lint:ignore RPC_REQUEST_RESPONSE_UNIQUE
LookupEntity(ctx context.Context, in *PermissionLookupEntityRequest, opts ...grpc.CallOption) (*PermissionLookupEntityResponse, error)
// LookupEntityStream method receives a PermissionLookupEntityRequest and streams a series of PermissionLookupEntityStreamResponse messages.
// It is used to retrieve entities by their identifiers in a streaming fashion.
+ // buf:lint:ignore RPC_REQUEST_RESPONSE_UNIQUE
+ // buf:lint:ignore RPC_REQUEST_STANDARD_NAME
LookupEntityStream(ctx context.Context, in *PermissionLookupEntityRequest, opts ...grpc.CallOption) (grpc.ServerStreamingClient[PermissionLookupEntityStreamResponse], error)
// LookupSubject method receives a PermissionLookupSubjectRequest and returns a PermissionLookupSubjectResponse.
// It is used to retrieve a subject by its identifier.
@@ -167,9 +170,12 @@ type PermissionServer interface {
Expand(context.Context, *PermissionExpandRequest) (*PermissionExpandResponse, error)
// LookupEntity method receives a PermissionLookupEntityRequest and returns a PermissionLookupEntityResponse.
// It is used to retrieve an entity by its identifier.
+ // buf:lint:ignore RPC_REQUEST_RESPONSE_UNIQUE
LookupEntity(context.Context, *PermissionLookupEntityRequest) (*PermissionLookupEntityResponse, error)
// LookupEntityStream method receives a PermissionLookupEntityRequest and streams a series of PermissionLookupEntityStreamResponse messages.
// It is used to retrieve entities by their identifiers in a streaming fashion.
+ // buf:lint:ignore RPC_REQUEST_RESPONSE_UNIQUE
+ // buf:lint:ignore RPC_REQUEST_STANDARD_NAME
LookupEntityStream(*PermissionLookupEntityRequest, grpc.ServerStreamingServer[PermissionLookupEntityStreamResponse]) error
// LookupSubject method receives a PermissionLookupSubjectRequest and returns a PermissionLookupSubjectResponse.
// It is used to retrieve a subject by its identifier.
@@ -750,16 +756,26 @@ type DataClient interface {
// The Write RPC method creates a new relation tuple.
Write(ctx context.Context, in *DataWriteRequest, opts ...grpc.CallOption) (*DataWriteResponse, error)
// RPC method to write relationships for a tenant. This can be accessed via a POST request to the given HTTP path. It's tagged under "Data" in OpenAPI documentation.
+ // buf:lint:ignore RPC_REQUEST_STANDARD_NAME
+ // buf:lint:ignore RPC_RESPONSE_STANDARD_NAME
WriteRelationships(ctx context.Context, in *RelationshipWriteRequest, opts ...grpc.CallOption) (*RelationshipWriteResponse, error)
// The ReadRelationships RPC method reads relation tuple(s).
+ // buf:lint:ignore RPC_REQUEST_STANDARD_NAME
+ // buf:lint:ignore RPC_RESPONSE_STANDARD_NAME
ReadRelationships(ctx context.Context, in *RelationshipReadRequest, opts ...grpc.CallOption) (*RelationshipReadResponse, error)
// The ReadAttributes RPC method reads attribute(s) of a relation.
+ // buf:lint:ignore RPC_REQUEST_STANDARD_NAME
+ // buf:lint:ignore RPC_RESPONSE_STANDARD_NAME
ReadAttributes(ctx context.Context, in *AttributeReadRequest, opts ...grpc.CallOption) (*AttributeReadResponse, error)
// The Delete RPC method deletes a relation tuple.
Delete(ctx context.Context, in *DataDeleteRequest, opts ...grpc.CallOption) (*DataDeleteResponse, error)
// RPC method to delete relationships for a tenant, accessed via a POST request to the specified path, tagged as "Data" in OpenAPI documentation.
+ // buf:lint:ignore RPC_REQUEST_STANDARD_NAME
+ // buf:lint:ignore RPC_RESPONSE_STANDARD_NAME
DeleteRelationships(ctx context.Context, in *RelationshipDeleteRequest, opts ...grpc.CallOption) (*RelationshipDeleteResponse, error)
// Executes or runs a specific bundle. This method is useful for processing or triggering actions based on the bundle's data.
+ // buf:lint:ignore RPC_REQUEST_STANDARD_NAME
+ // buf:lint:ignore RPC_RESPONSE_STANDARD_NAME
RunBundle(ctx context.Context, in *BundleRunRequest, opts ...grpc.CallOption) (*BundleRunResponse, error)
}
@@ -850,16 +866,26 @@ type DataServer interface {
// The Write RPC method creates a new relation tuple.
Write(context.Context, *DataWriteRequest) (*DataWriteResponse, error)
// RPC method to write relationships for a tenant. This can be accessed via a POST request to the given HTTP path. It's tagged under "Data" in OpenAPI documentation.
+ // buf:lint:ignore RPC_REQUEST_STANDARD_NAME
+ // buf:lint:ignore RPC_RESPONSE_STANDARD_NAME
WriteRelationships(context.Context, *RelationshipWriteRequest) (*RelationshipWriteResponse, error)
// The ReadRelationships RPC method reads relation tuple(s).
+ // buf:lint:ignore RPC_REQUEST_STANDARD_NAME
+ // buf:lint:ignore RPC_RESPONSE_STANDARD_NAME
ReadRelationships(context.Context, *RelationshipReadRequest) (*RelationshipReadResponse, error)
// The ReadAttributes RPC method reads attribute(s) of a relation.
+ // buf:lint:ignore RPC_REQUEST_STANDARD_NAME
+ // buf:lint:ignore RPC_RESPONSE_STANDARD_NAME
ReadAttributes(context.Context, *AttributeReadRequest) (*AttributeReadResponse, error)
// The Delete RPC method deletes a relation tuple.
Delete(context.Context, *DataDeleteRequest) (*DataDeleteResponse, error)
// RPC method to delete relationships for a tenant, accessed via a POST request to the specified path, tagged as "Data" in OpenAPI documentation.
+ // buf:lint:ignore RPC_REQUEST_STANDARD_NAME
+ // buf:lint:ignore RPC_RESPONSE_STANDARD_NAME
DeleteRelationships(context.Context, *RelationshipDeleteRequest) (*RelationshipDeleteResponse, error)
// Executes or runs a specific bundle. This method is useful for processing or triggering actions based on the bundle's data.
+ // buf:lint:ignore RPC_REQUEST_STANDARD_NAME
+ // buf:lint:ignore RPC_RESPONSE_STANDARD_NAME
RunBundle(context.Context, *BundleRunRequest) (*BundleRunResponse, error)
mustEmbedUnimplementedDataServer()
}
@@ -1275,12 +1301,18 @@ const (
type TenancyClient interface {
// Create is a unary RPC to create a new tenant.
// It requires a TenantCreateRequest and returns a TenantCreateResponse.
+ // buf:lint:ignore RPC_REQUEST_STANDARD_NAME
+ // buf:lint:ignore RPC_RESPONSE_STANDARD_NAME
Create(ctx context.Context, in *TenantCreateRequest, opts ...grpc.CallOption) (*TenantCreateResponse, error)
// Delete is a unary RPC to delete an existing tenant.
// It requires a TenantDeleteRequest and returns a TenantDeleteResponse.
+ // buf:lint:ignore RPC_REQUEST_STANDARD_NAME
+ // buf:lint:ignore RPC_RESPONSE_STANDARD_NAME
Delete(ctx context.Context, in *TenantDeleteRequest, opts ...grpc.CallOption) (*TenantDeleteResponse, error)
// List is a unary RPC to get a list of all tenants.
// It requires a TenantListRequest and returns a TenantListResponse.
+ // buf:lint:ignore RPC_REQUEST_STANDARD_NAME
+ // buf:lint:ignore RPC_RESPONSE_STANDARD_NAME
List(ctx context.Context, in *TenantListRequest, opts ...grpc.CallOption) (*TenantListResponse, error)
}
@@ -1328,12 +1360,18 @@ func (c *tenancyClient) List(ctx context.Context, in *TenantListRequest, opts ..
type TenancyServer interface {
// Create is a unary RPC to create a new tenant.
// It requires a TenantCreateRequest and returns a TenantCreateResponse.
+ // buf:lint:ignore RPC_REQUEST_STANDARD_NAME
+ // buf:lint:ignore RPC_RESPONSE_STANDARD_NAME
Create(context.Context, *TenantCreateRequest) (*TenantCreateResponse, error)
// Delete is a unary RPC to delete an existing tenant.
// It requires a TenantDeleteRequest and returns a TenantDeleteResponse.
+ // buf:lint:ignore RPC_REQUEST_STANDARD_NAME
+ // buf:lint:ignore RPC_RESPONSE_STANDARD_NAME
Delete(context.Context, *TenantDeleteRequest) (*TenantDeleteResponse, error)
// List is a unary RPC to get a list of all tenants.
// It requires a TenantListRequest and returns a TenantListResponse.
+ // buf:lint:ignore RPC_REQUEST_STANDARD_NAME
+ // buf:lint:ignore RPC_RESPONSE_STANDARD_NAME
List(context.Context, *TenantListRequest) (*TenantListResponse, error)
mustEmbedUnimplementedTenancyServer()
}
diff --git a/pkg/schema/loader.go b/pkg/schema/loader.go
index a1f57b9df..ac9fa5aaf 100644
--- a/pkg/schema/loader.go
+++ b/pkg/schema/loader.go
@@ -9,13 +9,16 @@ import ( // Package imports
"path/filepath" // Path utilities
"strings" // String utilities
) // End imports
+
// Type defines an enumeration for different schema types.
type Type int // Schema type enum
-const ( // Schema type constants
+
+const ( // Schema type constants
URL Type = iota // URL represents a schema type for URLs
File // File represents a schema type for file paths
Inline // Inline represents a schema type for inline data
) // End constants
+
// Loader is a struct that holds a map of loader functions, each corresponding to a Type.
type Loader struct {
// loaders is a map where each Type is associated with a corresponding function
@@ -23,6 +26,7 @@ type Loader struct {
// These functions are responsible for loading data based on the Type.
loaders map[Type]func(string) (string, error)
} // End Loader struct
+
// NewSchemaLoader initializes and returns a new Loader instance.
// It sets up the map of loader functions for each Type.
func NewSchemaLoader() *Loader {
@@ -34,6 +38,7 @@ func NewSchemaLoader() *Loader {
}, // End loaders map
} // End return
} // End NewSchemaLoader
+
// LoadSchema loads a schema based on its type
func (s *Loader) LoadSchema(input string) (string, error) {
schemaType, err := determineSchemaType(input)
@@ -46,6 +51,7 @@ func (s *Loader) LoadSchema(input string) (string, error) {
}
return loaderFunc(input) // Execute loader
} // End LoadSchema
+
// determineSchemaType determines the type of schema based on the input string
func determineSchemaType(input string) (Type, error) {
if isURL(input) { // Check URL first
@@ -60,6 +66,7 @@ func determineSchemaType(input string) (Type, error) {
}
return Inline, nil // Default to inline
} // End determineSchemaType
+
func isURL(input string) bool { // Check if input is URL
parsedURL, err := url.Parse(input)
if err != nil {
@@ -68,6 +75,7 @@ func isURL(input string) bool { // Check if input is URL
// Check if the URL has a valid scheme and host
return parsedURL.Scheme != "" && parsedURL.Host != ""
} // End isURL
+
func isFilePath(input string) (bool, error) { // Check if input is file
_, err := os.Stat(input) // Get file info
if err != nil {
@@ -81,6 +89,7 @@ func isFilePath(input string) (bool, error) { // Check if input is file
}
return true, nil // File exists
} // End isFilePath
+
func loadFromURL(inputURL string) (string, error) { // Load schema from URL
// Parse and validate the URL
parsedURL, err := url.Parse(inputURL)
@@ -105,6 +114,7 @@ func loadFromURL(inputURL string) (string, error) { // Load schema from URL
} // Read succeeded
return string(body), nil // Return body
} // End loadFromURL
+
func loadFromFile(path string) (string, error) { // Load schema from file
// Clean the path
cleanPath := filepath.Clean(path)
@@ -118,6 +128,7 @@ func loadFromFile(path string) (string, error) { // Load schema from file
} // Read succeeded
return string(content), nil // Return content
} // End loadFromFile
+
// loadInline is a function that handles inline schema types.
func loadInline(schema string) (string, error) { // Load inline schema
// Add validation if necessary. For example:
diff --git a/pkg/schema/loader_test.go b/pkg/schema/loader_test.go
index dcab61233..daefd6f0b 100644
--- a/pkg/schema/loader_test.go
+++ b/pkg/schema/loader_test.go
@@ -4,7 +4,8 @@ import ( // Package imports
// Test frameworks
. "github.com/onsi/ginkgo/v2" // BDD test framework
. "github.com/onsi/gomega" // Matcher library
-) // End imports
+) // End imports
+
var _ = Describe("Loader", func() { // Loader test suite
Context("LoadSchema function", func() { // LoadSchema tests
It("should load schema from URL", func() { // Test URL loading
diff --git a/pkg/telemetry/meterexporters/otlp_grpc.go b/pkg/telemetry/meterexporters/otlp_grpc.go
index 19a3027b6..ec2a288eb 100644
--- a/pkg/telemetry/meterexporters/otlp_grpc.go
+++ b/pkg/telemetry/meterexporters/otlp_grpc.go
@@ -6,6 +6,7 @@ import ( // gRPC metric dependencies
"go.opentelemetry.io/otel/sdk/metric" // Metric SDK
"google.golang.org/grpc/credentials" // TLS credentials
) // End imports
+
// NewOTLPGrpc - Creates new OTLP metric exporter using GRPC protocol for metrics collection.
func NewOTLPGrpc(
endpoint string,
diff --git a/pkg/telemetry/tracerexporters/otlp.go b/pkg/telemetry/tracerexporters/otlp.go
index b22fb8b83..963eb6710 100644
--- a/pkg/telemetry/tracerexporters/otlp.go
+++ b/pkg/telemetry/tracerexporters/otlp.go
@@ -8,6 +8,7 @@ import ( // OTLP trace dependencies
"go.opentelemetry.io/otel/sdk/trace" // Trace SDK
"google.golang.org/grpc/credentials" // TLS credentials
) // End imports
+
// NewOTLP - Creates new OTLP trace exporter based on protocol (HTTP or gRPC).
func NewOTLP(endpoint string, insecure bool, urlpath string, headers map[string]string, protocol string) (trace.SpanExporter, error) { // Create OTLP tracer
switch protocol { // Select protocol
diff --git a/proto/base/v1/base.proto b/proto/base/v1/base.proto
index e2efa0cff..c84cb07de 100644
--- a/proto/base/v1/base.proto
+++ b/proto/base/v1/base.proto
@@ -1,11 +1,11 @@
syntax = "proto3";
package base.v1;
+import "buf/validate/validate.proto";
import "google/api/expr/v1alpha1/checked.proto";
import "google/protobuf/any.proto";
import "google/protobuf/struct.proto";
import "google/protobuf/timestamp.proto";
-import "validate/validate.proto";
option go_package = "github.com/Permify/permify/pkg/pb/base/v1";
@@ -65,13 +65,13 @@ message Child {
// Child node can be either a leaf or a rewrite operation.
oneof type {
// Either leaf or rewrite operation is required.
- option (validate.required) = true;
+ option (buf.validate.oneof).required = true;
// Leaf node in the permission tree.
- Leaf leaf = 1 [(validate.rules).message.required = true];
+ Leaf leaf = 1;
// Rewrite operation in the permission tree.
- Rewrite rewrite = 2 [(validate.rules).message.required = true];
+ Rewrite rewrite = 2;
}
}
@@ -80,19 +80,19 @@ message Leaf {
// Leaf node can be one of several types.
oneof type {
// One type is required.
- option (validate.required) = true;
+ option (buf.validate.oneof).required = true;
// A computed set of users.
- ComputedUserSet computed_user_set = 1 [(validate.rules).message.required = true];
+ ComputedUserSet computed_user_set = 1;
// A tuple to user set conversion.
- TupleToUserSet tuple_to_user_set = 2 [(validate.rules).message.required = true];
+ TupleToUserSet tuple_to_user_set = 2;
// A computed attribute.
- ComputedAttribute computed_attribute = 3 [(validate.rules).message.required = true];
+ ComputedAttribute computed_attribute = 3;
// A call to a function or method.
- Call call = 4 [(validate.rules).message.required = true];
+ Call call = 4;
}
}
@@ -148,7 +148,7 @@ message EntityDefinition {
}
// The name of the entity, which follows a specific string pattern and has a maximum byte size.
- string name = 1 [(validate.rules).string = {
+ string name = 1 [(buf.validate.field).string = {
pattern: "^[a-zA-Z_]{1,64}$"
max_bytes: 64
}];
@@ -169,7 +169,7 @@ message EntityDefinition {
// The RuleDefinition message provides detailed information about a specific rule.
message RuleDefinition {
// The name of the rule, which follows a specific string pattern and has a maximum byte size.
- string name = 1 [(validate.rules).string = {
+ string name = 1 [(buf.validate.field).string = {
pattern: "^[a-zA-Z_]{1,64}$"
max_bytes: 64
}];
@@ -184,7 +184,7 @@ message RuleDefinition {
// The AttributeDefinition message provides detailed information about a specific attribute.
message AttributeDefinition {
// The name of the attribute, which follows a specific string pattern and has a maximum byte size.
- string name = 1 [(validate.rules).string = {
+ string name = 1 [(buf.validate.field).string = {
pattern: "^[a-zA-Z_]{1,64}$"
max_bytes: 64
}];
@@ -196,7 +196,7 @@ message AttributeDefinition {
// The RelationDefinition message provides detailed information about a specific relation.
message RelationDefinition {
// The name of the relation, which follows a specific string pattern and has a maximum byte size.
- string name = 1 [(validate.rules).string = {
+ string name = 1 [(buf.validate.field).string = {
pattern: "^[a-zA-Z_]{1,64}$"
max_bytes: 64
}];
@@ -208,7 +208,7 @@ message RelationDefinition {
// The PermissionDefinition message provides detailed information about a specific permission.
message PermissionDefinition {
// The name of the permission, which follows a specific string pattern and has a maximum byte size.
- string name = 1 [(validate.rules).string = {
+ string name = 1 [(buf.validate.field).string = {
pattern: "^[a-zA-Z_]{1,64}$"
max_bytes: 64
}];
@@ -220,28 +220,30 @@ message PermissionDefinition {
// The RelationReference message provides a reference to a specific relation.
message RelationReference {
// The type of the referenced entity, which follows a specific string pattern and has a maximum byte size.
- string type = 1 [(validate.rules).string = {
+ string type = 1 [(buf.validate.field).string = {
pattern: "^[a-zA-Z_]{1,64}$"
max_bytes: 64
}];
// The name of the referenced relation, which follows a specific string pattern and has a maximum byte size.
- string relation = 2 [(validate.rules).string = {
- pattern: "^[a-zA-Z_]{1,64}$"
- max_bytes: 64
- ignore_empty: true
- }];
+ string relation = 2 [
+ (buf.validate.field).string = {
+ pattern: "^[a-zA-Z_]{1,64}$"
+ max_bytes: 64
+ },
+ (buf.validate.field).ignore = IGNORE_IF_ZERO_VALUE
+ ];
}
message Entrance {
// The type of the entrance entity, which follows a specific string pattern and has a maximum byte size.
- string type = 1 [(validate.rules).string = {
+ string type = 1 [(buf.validate.field).string = {
pattern: "^[a-zA-Z_]{1,64}$"
max_bytes: 64
}];
// The value associated with the entrance, which follows a specific string pattern and has a maximum byte size.
- string value = 2 [(validate.rules).string = {
+ string value = 2 [(buf.validate.field).string = {
pattern: "^[a-zA-Z_]{1,64}$"
max_bytes: 64
}];
@@ -262,7 +264,7 @@ message Call {
// ComputedAttribute defines a computed attribute which includes its name.
message ComputedAttribute {
- string name = 1 [(validate.rules).string = {
+ string name = 1 [(buf.validate.field).string = {
pattern: "^[a-zA-Z_]{1,64}$"
max_bytes: 64
}]; // Name of the computed attribute
@@ -270,7 +272,7 @@ message ComputedAttribute {
// ComputedUserSet defines a set of computed users which includes the relation name.
message ComputedUserSet {
- string relation = 1 [(validate.rules).string = {
+ string relation = 1 [(buf.validate.field).string = {
pattern: "^[a-zA-Z_]{1,64}$"
max_bytes: 64
}]; // Relation name
@@ -284,7 +286,7 @@ message TupleToUserSet {
// TupleSet represents a set of tuples associated with a specific relation.
message TupleSet {
- string relation = 1 [(validate.rules).string = {
+ string relation = 1 [(buf.validate.field).string = {
pattern: "^[a-zA-Z_]{1,64}$"
max_bytes: 64
}];
@@ -294,12 +296,12 @@ message TupleSet {
message Tuple {
Entity entity = 1 [
json_name = "entity",
- (validate.rules).message.required = true
+ (buf.validate.field).required = true
];
string relation = 2 [
json_name = "relation",
- (validate.rules).string = {
+ (buf.validate.field).string = {
pattern: "^[a-zA-Z_]{1,64}$"
max_bytes: 64
}
@@ -307,7 +309,7 @@ message Tuple {
Subject subject = 3 [
json_name = "subject",
- (validate.rules).message.required = true
+ (buf.validate.field).required = true
];
}
@@ -315,7 +317,7 @@ message Tuple {
message Attribute {
Entity entity = 1 [
json_name = "entity",
- (validate.rules).message.required = true
+ (buf.validate.field).required = true
];
string attribute = 2 [json_name = "attribute"]; // Name of the attribute
@@ -337,7 +339,7 @@ message Attributes {
message Entity {
string type = 1 [
json_name = "type",
- (validate.rules).string = {
+ (buf.validate.field).string = {
pattern: "^[a-zA-Z_]{1,64}$"
max_bytes: 64
}
@@ -345,7 +347,7 @@ message Entity {
string id = 2 [
json_name = "id",
- (validate.rules).string = {
+ (buf.validate.field).string = {
pattern: "^([a-zA-Z0-9_\\-@\\.:+]{1,128}|\\*)$"
max_bytes: 128
}
@@ -356,12 +358,12 @@ message Entity {
message EntityAndRelation {
Entity entity = 1 [
json_name = "entity",
- (validate.rules).message.required = true
+ (buf.validate.field).required = true
];
string relation = 2 [
json_name = "relation",
- (validate.rules).string = {
+ (buf.validate.field).string = {
pattern: "^[a-zA-Z_]{1,64}$"
max_bytes: 64
}
@@ -372,7 +374,7 @@ message EntityAndRelation {
message Subject {
string type = 1 [
json_name = "type",
- (validate.rules).string = {
+ (buf.validate.field).string = {
pattern: "^[a-zA-Z_]{1,64}$"
max_bytes: 64
}
@@ -380,7 +382,7 @@ message Subject {
string id = 2 [
json_name = "id",
- (validate.rules).string = {
+ (buf.validate.field).string = {
pattern: "^([a-zA-Z0-9_\\-@\\.:+]{1,128}|\\*)$"
max_bytes: 128
}
@@ -388,11 +390,11 @@ message Subject {
string relation = 3 [
json_name = "relation",
- (validate.rules).string = {
+ (buf.validate.field).string = {
pattern: "^[a-zA-Z_]{1,64}$"
max_bytes: 64
- ignore_empty: true
- }
+ },
+ (buf.validate.field).ignore = IGNORE_IF_ZERO_VALUE
];
}
@@ -409,11 +411,11 @@ message TupleFilter {
string relation = 2 [
json_name = "relation",
- (validate.rules).string = {
+ (buf.validate.field).string = {
pattern: "^[a-zA-Z_]{1,64}$"
max_bytes: 64
- ignore_empty: true
- }
+ },
+ (buf.validate.field).ignore = IGNORE_IF_ZERO_VALUE
];
SubjectFilter subject = 3 [json_name = "subject"]; // The subject filter
@@ -434,11 +436,11 @@ message SubjectFilter {
string relation = 3 [
json_name = "relation",
- (validate.rules).string = {
+ (buf.validate.field).string = {
pattern: "^[a-zA-Z_]{1,64}$"
max_bytes: 64
- ignore_empty: true
- }
+ },
+ (buf.validate.field).ignore = IGNORE_IF_ZERO_VALUE
];
}
@@ -482,7 +484,7 @@ message Expand {
// ExpandLeaf is the leaf node of an Expand tree and can be either a set of Subjects or a set of Values.
message ExpandLeaf {
oneof type { // type can be either Subjects or Values.
- option (validate.required) = true;
+ option (buf.validate.oneof).required = true;
// subjects are used when the leaf is a set of subjects.
Subjects subjects = 1 [json_name = "subjects"];
@@ -529,7 +531,7 @@ message DataChange {
Operation operation = 1 [json_name = "operation"]; // The operation type.
oneof type { // The type of the change which can be either a tuple or an attribute.
- option (validate.required) = true;
+ option (buf.validate.oneof).required = true;
Tuple tuple = 2 [json_name = "tuple"]; // If the change is a tuple.
Attribute attribute = 3 [json_name = "attribute"]; // If the change is an attribute.
}
diff --git a/proto/base/v1/service.proto b/proto/base/v1/service.proto
index fdb64090c..bfdab9573 100644
--- a/proto/base/v1/service.proto
+++ b/proto/base/v1/service.proto
@@ -2,11 +2,12 @@ syntax = "proto3";
package base.v1;
import "base/v1/base.proto";
+import "buf/validate/validate.proto";
import "google/api/annotations.proto";
import "protoc-gen-openapiv2/options/annotations.proto";
-import "validate/validate.proto";
option go_package = "github.com/Permify/permify/pkg/pb/base/v1";
+
// ** PERMISSION SERVICE **
// Permission service contains methods to interact with permissions.
service Permission {
@@ -791,10 +792,9 @@ message PermissionCheckRequest {
// Identifier of the tenant, required, and must match the pattern "[a-zA-Z0-9-,]+", max 64 bytes.
string tenant_id = 1 [
json_name = "tenant_id",
- (validate.rules).string = {
+ (buf.validate.field).string = {
pattern: "^([a-zA-Z0-9_\\-@\\.:+]{1,128}|\\*)$"
max_bytes: 128
- ignore_empty: false
},
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {description: "Identifier of the tenant, if you are not using multi-tenancy (have only one tenant) use pre-inserted tenant t1 for this field. Required, and must match the pattern \\“[a-zA-Z0-9-,]+\\“, max 64 bytes."}
];
@@ -802,23 +802,22 @@ message PermissionCheckRequest {
// Metadata associated with this request, required.
PermissionCheckRequestMetadata metadata = 2 [
json_name = "metadata",
- (validate.rules).message.required = true
+ (buf.validate.field).required = true
];
// Entity on which the permission needs to be checked, required.
Entity entity = 3 [
json_name = "entity",
- (validate.rules).message.required = true,
+ (buf.validate.field).required = true,
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {example: "\"repository:1\""}
];
// Name of the permission or relation, required, must start with a letter and can include alphanumeric and underscore, max 64 bytes.
string permission = 4 [
json_name = "permission",
- (validate.rules).string = {
+ (buf.validate.field).string = {
pattern: "^[a-zA-Z_]{1,64}$"
max_bytes: 64
- ignore_empty: false
},
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {description: "The action the user wants to perform on the resource"}
];
@@ -826,7 +825,7 @@ message PermissionCheckRequest {
// Subject for which the permission needs to be checked, required.
Subject subject = 5 [
json_name = "subject",
- (validate.rules).message.required = true
+ (buf.validate.field).required = true
];
// Context associated with this request.
@@ -853,7 +852,7 @@ message PermissionCheckRequestMetadata {
// Depth of the check, must be greater than or equal to 3.
int32 depth = 3 [
json_name = "depth",
- (validate.rules).int32.gte = 3,
+ (buf.validate.field).int32.gte = 3,
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {description: "Query limit when if recursive database queries got in loop"}
];
}
@@ -878,17 +877,16 @@ message PermissionBulkCheckRequestItem {
// Entity on which the permission needs to be checked, required.
Entity entity = 1 [
json_name = "entity",
- (validate.rules).message.required = true,
+ (buf.validate.field).required = true,
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {example: "\"repository:1\""}
];
// Name of the permission or relation, required, must start with a letter and can include alphanumeric and underscore, max 64 bytes.
string permission = 2 [
json_name = "permission",
- (validate.rules).string = {
+ (buf.validate.field).string = {
pattern: "^[a-zA-Z_]{1,64}$"
max_bytes: 64
- ignore_empty: false
},
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {description: "The action the user wants to perform on the resource"}
];
@@ -896,18 +894,18 @@ message PermissionBulkCheckRequestItem {
// Subject for which the permission needs to be checked, required.
Subject subject = 3 [
json_name = "subject",
- (validate.rules).message.required = true
+ (buf.validate.field).required = true
];
}
+
// PermissionBulkCheckRequest is the request message for the BulkCheck method in the Permission service.
message PermissionBulkCheckRequest {
// Identifier of the tenant, required, and must match the pattern "[a-zA-Z0-9-,]+", max 64 bytes.
string tenant_id = 1 [
json_name = "tenant_id",
- (validate.rules).string = {
+ (buf.validate.field).string = {
pattern: "^([a-zA-Z0-9_\\-@\\.:+]{1,128}|\\*)$"
max_bytes: 128
- ignore_empty: false
},
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {description: "Identifier of the tenant, if you are not using multi-tenancy (have only one tenant) use pre-inserted tenant t1 for this field. Required, and must match the pattern \\“[a-zA-Z0-9-,]+\\“, max 64 bytes."}
];
@@ -915,13 +913,13 @@ message PermissionBulkCheckRequest {
// Metadata associated with this request, required.
PermissionCheckRequestMetadata metadata = 2 [
json_name = "metadata",
- (validate.rules).message.required = true
+ (buf.validate.field).required = true
];
// List of permission check requests, maximum 100 items.
repeated PermissionBulkCheckRequestItem items = 3 [
json_name = "items",
- (validate.rules).repeated = {
+ (buf.validate.field).repeated = {
min_items: 1
max_items: 100
}
@@ -950,10 +948,9 @@ message PermissionExpandRequest {
// Identifier of the tenant, required, and must match the pattern "[a-zA-Z0-9-,]+", max 64 bytes.
string tenant_id = 1 [
json_name = "tenant_id",
- (validate.rules).string = {
+ (buf.validate.field).string = {
pattern: "^([a-zA-Z0-9_\\-@\\.:+]{1,128}|\\*)$"
max_bytes: 128
- ignore_empty: false
},
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {description: "Identifier of the tenant, if you are not using multi-tenancy (have only one tenant) use pre-inserted tenant t1 for this field. Required, and must match the pattern \\“[a-zA-Z0-9-,]+\\“, max 64 bytes."}
];
@@ -961,23 +958,23 @@ message PermissionExpandRequest {
// Metadata associated with this request, required.
PermissionExpandRequestMetadata metadata = 2 [
json_name = "metadata",
- (validate.rules).message.required = true
+ (buf.validate.field).required = true
];
// Entity on which the permission needs to be expanded, required.
Entity entity = 3 [
json_name = "entity",
- (validate.rules).message.required = true
+ (buf.validate.field).required = true
];
// Name of the permission to be expanded, not required, must start with a letter and can include alphanumeric and underscore, max 64 bytes.
string permission = 4 [
json_name = "permission",
- (validate.rules).string = {
+ (buf.validate.field).string = {
pattern: "^[a-zA-Z_]{1,64}$"
max_bytes: 64
- ignore_empty: true
- }
+ },
+ (buf.validate.field).ignore = IGNORE_IF_ZERO_VALUE
];
// Context associated with this request.
@@ -1012,10 +1009,9 @@ message PermissionLookupEntityRequest {
// Identifier of the tenant, required, and must match the pattern "[a-zA-Z0-9-,]+", max 64 bytes.
string tenant_id = 1 [
json_name = "tenant_id",
- (validate.rules).string = {
+ (buf.validate.field).string = {
pattern: "^([a-zA-Z0-9_\\-@\\.:+]{1,128}|\\*)$"
max_bytes: 128
- ignore_empty: false
},
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {description: "Identifier of the tenant, if you are not using multi-tenancy (have only one tenant) use pre-inserted tenant t1 for this field. Required, and must match the pattern \\“[a-zA-Z0-9-,]+\\“, max 64 bytes."}
];
@@ -1023,33 +1019,31 @@ message PermissionLookupEntityRequest {
// Metadata associated with this request, required.
PermissionLookupEntityRequestMetadata metadata = 2 [
json_name = "metadata",
- (validate.rules).message.required = true
+ (buf.validate.field).required = true
];
// Type of the entity to lookup, required, must start with a letter and can include alphanumeric and underscore, max 64 bytes.
string entity_type = 3 [
json_name = "entity_type",
- (validate.rules).string = {
+ (buf.validate.field).string = {
pattern: "^[a-zA-Z_]{1,64}$"
max_bytes: 64
- ignore_empty: false
}
];
// Name of the permission to check, required, must start with a letter and can include alphanumeric and underscore, max 64 bytes.
string permission = 4 [
json_name = "permission",
- (validate.rules).string = {
+ (buf.validate.field).string = {
pattern: "^[a-zA-Z_]{1,64}$"
max_bytes: 64
- ignore_empty: false
}
];
// Subject for which to check the permission, required.
Subject subject = 5 [
json_name = "subject",
- (validate.rules).message.required = true
+ (buf.validate.field).required = true
];
// Context associated with this request.
@@ -1063,17 +1057,16 @@ message PermissionLookupEntityRequest {
// The value should be between 1 and 100.
uint32 page_size = 8 [
json_name = "page_size",
- (validate.rules).uint32 = {
- gte: 1
- ignore_empty: true
- }
+ (buf.validate.field).uint32 = {gte: 1},
+ (buf.validate.field).ignore = IGNORE_IF_ZERO_VALUE
];
// continuous_token is an optional parameter used for pagination.
// It should be the value received in the previous response.
string continuous_token = 9 [
json_name = "continuous_token",
- (validate.rules).string = {ignore_empty: true}
+ (buf.validate.field).string = {},
+ (buf.validate.field).ignore = IGNORE_IF_ZERO_VALUE
];
}
@@ -1091,7 +1084,7 @@ message PermissionLookupEntityRequestMetadata {
// Depth of lookup, required, must be greater or equal to 3.
int32 depth = 3 [
json_name = "depth",
- (validate.rules).int32.gte = 3,
+ (buf.validate.field).int32.gte = 3,
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {description: "Query limit when if recursive database queries got in loop."}
];
}
@@ -1121,10 +1114,9 @@ message PermissionEntityFilterRequest {
// Identifier of the tenant, required, and must match the pattern "[a-zA-Z0-9-,]+", max 64 bytes.
string tenant_id = 1 [
json_name = "tenant_id",
- (validate.rules).string = {
+ (buf.validate.field).string = {
pattern: "^([a-zA-Z0-9_\\-@\\.:+]{1,128}|\\*)$"
max_bytes: 128
- ignore_empty: false
},
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {description: "Identifier of the tenant, if you are not using multi-tenancy (have only one tenant) use pre-inserted tenant t1 for this field. Required, and must match the pattern \\“[a-zA-Z0-9-,]+\\“, max 64 bytes."}
];
@@ -1132,7 +1124,7 @@ message PermissionEntityFilterRequest {
// Metadata associated with this request, required.
PermissionEntityFilterRequestMetadata metadata = 2 [
json_name = "metadata",
- (validate.rules).message.required = true
+ (buf.validate.field).required = true
];
// Reference to the entity to filter.
@@ -1152,7 +1144,8 @@ message PermissionEntityFilterRequest {
// It should be the value received in the previous response.
string cursor = 7 [
json_name = "cursor",
- (validate.rules).string = {ignore_empty: true}
+ (buf.validate.field).string = {},
+ (buf.validate.field).ignore = IGNORE_IF_ZERO_VALUE
];
}
@@ -1170,7 +1163,7 @@ message PermissionEntityFilterRequestMetadata {
// Depth of lookup, required, must be greater or equal to 3.
int32 depth = 3 [
json_name = "depth",
- (validate.rules).int32.gte = 3,
+ (buf.validate.field).int32.gte = 3,
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {description: "Query limit when if recursive database queries got in loop."}
];
}
@@ -1182,10 +1175,9 @@ message PermissionLookupSubjectRequest {
// Identifier of the tenant, required, and must match the pattern "[a-zA-Z0-9-,]+", max 64 bytes.
string tenant_id = 1 [
json_name = "tenant_id",
- (validate.rules).string = {
+ (buf.validate.field).string = {
pattern: "^([a-zA-Z0-9_\\-@\\.:+]{1,128}|\\*)$"
max_bytes: 128
- ignore_empty: false
},
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {description: "Identifier of the tenant, if you are not using multi-tenancy (have only one tenant) use pre-inserted tenant t1 for this field. Required, and must match the pattern \\“[a-zA-Z0-9-,]+\\“, max 64 bytes."}
];
@@ -1193,29 +1185,28 @@ message PermissionLookupSubjectRequest {
// Metadata associated with this request, required.
PermissionLookupSubjectRequestMetadata metadata = 2 [
json_name = "metadata",
- (validate.rules).message.required = true
+ (buf.validate.field).required = true
];
// Entity for which to check the permission, required.
Entity entity = 3 [
json_name = "entity",
- (validate.rules).message.required = true
+ (buf.validate.field).required = true
];
// Permission to be checked, can be a permission or relation. Required, and must match the pattern "^([a-zA-Z][a-zA-Z0-9_]{1,62}[a-zA-Z0-9])$", max 64 bytes.
string permission = 4 [
json_name = "permission",
- (validate.rules).string = {
+ (buf.validate.field).string = {
pattern: "^[a-zA-Z_]{1,64}$"
max_bytes: 64
- ignore_empty: false
}
];
// Reference to the subject to lookup.
RelationReference subject_reference = 5 [
json_name = "subject_reference",
- (validate.rules).message.required = true
+ (buf.validate.field).required = true
];
// Context associated with this request.
@@ -1228,17 +1219,16 @@ message PermissionLookupSubjectRequest {
// The value should be between 1 and 100.
uint32 page_size = 8 [
json_name = "page_size",
- (validate.rules).uint32 = {
- gte: 1
- ignore_empty: true
- }
+ (buf.validate.field).uint32 = {gte: 1},
+ (buf.validate.field).ignore = IGNORE_IF_ZERO_VALUE
];
// continuous_token is an optional parameter used for pagination.
// It should be the value received in the previous response.
string continuous_token = 9 [
json_name = "continuous_token",
- (validate.rules).string = {ignore_empty: true}
+ (buf.validate.field).string = {},
+ (buf.validate.field).ignore = IGNORE_IF_ZERO_VALUE
];
}
@@ -1256,7 +1246,7 @@ message PermissionLookupSubjectRequestMetadata {
// Depth of the check, must be greater than or equal to 3.
int32 depth = 3 [
json_name = "depth",
- (validate.rules).int32.gte = 3,
+ (buf.validate.field).int32.gte = 3,
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {description: "Query limit when if recursive database queries got in loop."}
];
}
@@ -1277,10 +1267,9 @@ message PermissionSubjectPermissionRequest {
// Identifier of the tenant, required, and must match the pattern "[a-zA-Z0-9-,]+", max 64 bytes.
string tenant_id = 1 [
json_name = "tenant_id",
- (validate.rules).string = {
+ (buf.validate.field).string = {
pattern: "^([a-zA-Z0-9_\\-@\\.:+]{1,128}|\\*)$"
max_bytes: 128
- ignore_empty: false
},
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {description: "Identifier of the tenant, if you are not using multi-tenancy (have only one tenant) use pre-inserted tenant t1 for this field. Required, and must match the pattern \\“[a-zA-Z0-9-,]+\\“, max 64 bytes."}
];
@@ -1288,19 +1277,19 @@ message PermissionSubjectPermissionRequest {
// Metadata associated with this request, required.
PermissionSubjectPermissionRequestMetadata metadata = 2 [
json_name = "metadata",
- (validate.rules).message.required = true
+ (buf.validate.field).required = true
];
// Entity for which to check the permission, required.
Entity entity = 3 [
json_name = "entity",
- (validate.rules).message.required = true
+ (buf.validate.field).required = true
];
// Subject for which to check the permission, required.
Subject subject = 4 [
json_name = "subject",
- (validate.rules).message.required = true
+ (buf.validate.field).required = true
];
// Context associated with this request.
@@ -1324,7 +1313,7 @@ message PermissionSubjectPermissionRequestMetadata {
// Depth of the check, must be greater than or equal to 3.
int32 depth = 4 [
json_name = "depth",
- (validate.rules).int32.gte = 3,
+ (buf.validate.field).int32.gte = 3,
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {description: "Query limit when if recursive database queries got in loop."}
];
}
@@ -1436,10 +1425,9 @@ message WatchRequest {
// Identifier of the tenant, required, and must match the pattern "[a-zA-Z0-9-,]+", max 64 bytes.
string tenant_id = 1 [
json_name = "tenant_id",
- (validate.rules).string = {
+ (buf.validate.field).string = {
pattern: "^([a-zA-Z0-9_\\-@\\.:+]{1,128}|\\*)$"
max_bytes: 128
- ignore_empty: false
},
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {description: "Identifier of the tenant, if you are not using multi-tenancy (have only one tenant) use pre-inserted tenant t1 for this field. Required, and must match the pattern \\“[a-zA-Z0-9-,]+\\“, max 64 bytes."}
];
@@ -1772,7 +1760,7 @@ service Schema {
}
fields: { // cURL example for listing schemas
key: "source" // Source code example
- value: {string_value: // cURL command string
+ value: {string_value: /* cURL command string */
"curl --location --request POST 'localhost:3476/v1/tenants/{tenant_id}/schemas/list' \\\n" // List schemas endpoint
"--header 'Content-Type: application/json' \\\n"
"--data-raw '{\n"
@@ -1799,10 +1787,9 @@ message SchemaWriteRequest {
// be a maximum of 64 bytes, and must not be empty.
string tenant_id = 1 [
json_name = "tenant_id",
- (validate.rules).string = {
+ (buf.validate.field).string = {
pattern: "^([a-zA-Z0-9_\\-@\\.:+]{1,128}|\\*)$"
max_bytes: 128
- ignore_empty: false
},
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {description: "Identifier of the tenant, if you are not using multi-tenancy (have only one tenant) use pre-inserted tenant t1 for this field. Required, and must match the pattern \\“[a-zA-Z0-9-,]+\\“, max 64 bytes."}
];
@@ -1827,17 +1814,16 @@ message SchemaPartialWriteRequest {
// be a maximum of 64 bytes, and must not be empty.
string tenant_id = 1 [
json_name = "tenant_id",
- (validate.rules).string = {
+ (buf.validate.field).string = {
pattern: "^([a-zA-Z0-9_\\-@\\.:+]{1,128}|\\*)$"
max_bytes: 128
- ignore_empty: false
}
];
// metadata is the additional information needed for the Partial Write request.
SchemaPartialWriteRequestMetadata metadata = 2 [
json_name = "metadata",
- (validate.rules).message.required = true
+ (buf.validate.field).required = true
];
// Map of entity name with the values needed to be updated
@@ -1867,10 +1853,9 @@ message SchemaReadRequest {
// be a maximum of 64 bytes, and must not be empty.
string tenant_id = 1 [
json_name = "tenant_id",
- (validate.rules).string = {
+ (buf.validate.field).string = {
pattern: "^([a-zA-Z0-9_\\-@\\.:+]{1,128}|\\*)$"
max_bytes: 128
- ignore_empty: false
},
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {description: "Identifier of the tenant, if you are not using multi-tenancy (have only one tenant) use pre-inserted tenant t1 for this field. Required, and must match the pattern \\“[a-zA-Z0-9-,]+\\“, max 64 bytes."}
];
@@ -1878,7 +1863,7 @@ message SchemaReadRequest {
// metadata is the additional information needed for the Read request.
SchemaReadRequestMetadata metadata = 2 [
json_name = "metadata",
- (validate.rules).message.required = true
+ (buf.validate.field).required = true
];
}
@@ -1905,10 +1890,9 @@ message SchemaListRequest {
// be a maximum of 64 bytes, and must not be empty.
string tenant_id = 1 [
json_name = "tenant_id",
- (validate.rules).string = {
+ (buf.validate.field).string = {
pattern: "^([a-zA-Z0-9_\\-@\\.:+]{1,128}|\\*)$"
max_bytes: 128
- ignore_empty: false
},
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {description: "Identifier of the tenant, if you are not using multi-tenancy (have only one tenant) use pre-inserted tenant t1 for this field. Required, and must match the pattern \\“[a-zA-Z0-9-,]+\\“, max 64 bytes."}
];
@@ -1917,17 +1901,16 @@ message SchemaListRequest {
// The value should be between 1 and 100.
uint32 page_size = 2 [
json_name = "page_size",
- (validate.rules).uint32 = {
- gte: 1
- ignore_empty: true
- }
+ (buf.validate.field).uint32 = {gte: 1},
+ (buf.validate.field).ignore = IGNORE_IF_ZERO_VALUE
];
// continuous_token is an optional parameter used for pagination.
// It should be the value received in the previous response.
string continuous_token = 3 [
json_name = "continuous_token",
- (validate.rules).string = {ignore_empty: true}
+ (buf.validate.field).string = {},
+ (buf.validate.field).ignore = IGNORE_IF_ZERO_VALUE
];
}
@@ -2666,10 +2649,9 @@ message DataWriteRequest {
// tenant_id represents the unique identifier of the tenant for which data is written.
string tenant_id = 1 [
json_name = "tenant_id",
- (validate.rules).string = {
+ (buf.validate.field).string = {
pattern: "^([a-zA-Z0-9_\\-@\\.:+]{1,128}|\\*)$"
max_bytes: 128
- ignore_empty: false
},
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {description: "Identifier of the tenant, if you are not using multi-tenancy (have only one tenant) use pre-inserted tenant t1 for this field. Required, and must match the pattern \\“[a-zA-Z0-9-,]+\\“, max 64 bytes."}
];
@@ -2677,29 +2659,19 @@ message DataWriteRequest {
// metadata holds additional data related to the request.
DataWriteRequestMetadata metadata = 2 [
json_name = "metadata",
- (validate.rules).message.required = true
+ (buf.validate.field).required = true
];
// tuples contains the list of tuples (entity-relation-entity triples) that need to be written.
repeated Tuple tuples = 3 [
json_name = "tuples",
- (validate.rules).repeated = {
- min_items: 0
- items: {
- message: {required: true}
- }
- }
+ (buf.validate.field).repeated.min_items = 0
];
// attributes contains the list of attributes (entity-attribute-value triples) that need to be written.
repeated Attribute attributes = 4 [
json_name = "attributes",
- (validate.rules).repeated = {
- min_items: 0
- items: {
- message: {required: true}
- }
- }
+ (buf.validate.field).repeated.min_items = 0
];
}
@@ -2725,10 +2697,9 @@ message RelationshipWriteRequest {
// Unique identifier for the tenant with specific constraints.
string tenant_id = 1 [
json_name = "tenant_id",
- (validate.rules).string = {
+ (buf.validate.field).string = {
pattern: "^([a-zA-Z0-9_\\-@\\.:+]{1,128}|\\*)$"
max_bytes: 128
- ignore_empty: false
},
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {description: "Identifier of the tenant, if you are not using multi-tenancy (have only one tenant) use pre-inserted tenant t1 for this field. Required, and must match the pattern \\“[a-zA-Z0-9-,]+\\“, max 64 bytes."}
];
@@ -2736,18 +2707,13 @@ message RelationshipWriteRequest {
// Metadata for the request. It's required.
RelationshipWriteRequestMetadata metadata = 2 [
json_name = "metadata",
- (validate.rules).message.required = true
+ (buf.validate.field).required = true
];
// List of tuples for the request. Must have between 1 and 100 items.
repeated Tuple tuples = 3 [
json_name = "tuples",
- (validate.rules).repeated = {
- min_items: 1
- items: {
- message: {required: true}
- }
- }
+ (buf.validate.field).repeated.min_items = 1
];
}
@@ -2770,10 +2736,9 @@ message RelationshipReadRequest {
// tenant_id represents the unique identifier of the tenant for which relationships are read.
string tenant_id = 1 [
json_name = "tenant_id",
- (validate.rules).string = {
+ (buf.validate.field).string = {
pattern: "^([a-zA-Z0-9_\\-@\\.:+]{1,128}|\\*)$"
max_bytes: 128
- ignore_empty: false
},
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {description: "Identifier of the tenant, if you are not using multi-tenancy (have only one tenant) use pre-inserted tenant t1 for this field. Required, and must match the pattern \\“[a-zA-Z0-9-,]+\\“, max 64 bytes."}
];
@@ -2781,29 +2746,28 @@ message RelationshipReadRequest {
// metadata holds additional data related to the request.
RelationshipReadRequestMetadata metadata = 2 [
json_name = "metadata",
- (validate.rules).message.required = true
+ (buf.validate.field).required = true
];
// filter is used to specify criteria for the data that needs to be read.
TupleFilter filter = 3 [
json_name = "filter",
- (validate.rules).message.required = true
+ (buf.validate.field).required = true
];
// page_size specifies the number of results to return in a single page.
// If more results are available, a continuous_token is included in the response.
uint32 page_size = 4 [
json_name = "page_size",
- (validate.rules).uint32 = {
- gte: 1
- ignore_empty: true
- }
+ (buf.validate.field).uint32 = {gte: 1},
+ (buf.validate.field).ignore = IGNORE_IF_ZERO_VALUE
];
// continuous_token is used in case of paginated reads to get the next page of results.
string continuous_token = 5 [
json_name = "continuous_token",
- (validate.rules).string = {ignore_empty: true}
+ (buf.validate.field).string = {},
+ (buf.validate.field).ignore = IGNORE_IF_ZERO_VALUE
];
}
@@ -2833,10 +2797,9 @@ message AttributeReadRequest {
// tenant_id represents the unique identifier of the tenant from which the attributes are being read.
string tenant_id = 1 [
json_name = "tenant_id",
- (validate.rules).string = {
+ (buf.validate.field).string = {
pattern: "^([a-zA-Z0-9_\\-@\\.:+]{1,128}|\\*)$"
max_bytes: 128
- ignore_empty: false
},
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {description: "Identifier of the tenant, if you are not using multi-tenancy (have only one tenant) use pre-inserted tenant t1 for this field. Required, and must match the pattern \\“[a-zA-Z0-9-,]+\\“, max 64 bytes."}
];
@@ -2844,29 +2807,28 @@ message AttributeReadRequest {
// metadata holds additional information related to the request.
AttributeReadRequestMetadata metadata = 2 [
json_name = "metadata",
- (validate.rules).message.required = true
+ (buf.validate.field).required = true
];
// filter specifies the criteria used to select the attributes that should be returned.
AttributeFilter filter = 3 [
json_name = "filter",
- (validate.rules).message.required = true
+ (buf.validate.field).required = true
];
// page_size specifies the number of results to return in a single page.
// If more results are available, a continuous_token is included in the response.
uint32 page_size = 4 [
json_name = "page_size",
- (validate.rules).uint32 = {
- gte: 1
- ignore_empty: true
- }
+ (buf.validate.field).uint32 = {gte: 1},
+ (buf.validate.field).ignore = IGNORE_IF_ZERO_VALUE
];
// continuous_token is used in case of paginated reads to get the next page of results.
string continuous_token = 5 [
json_name = "continuous_token",
- (validate.rules).string = {ignore_empty: true}
+ (buf.validate.field).string = {},
+ (buf.validate.field).ignore = IGNORE_IF_ZERO_VALUE
];
}
@@ -2896,10 +2858,9 @@ message DataDeleteRequest {
// tenant_id represents the unique identifier of the tenant from which the data will be deleted.
string tenant_id = 1 [
json_name = "tenant_id",
- (validate.rules).string = {
+ (buf.validate.field).string = {
pattern: "^([a-zA-Z0-9_\\-@\\.:+]{1,128}|\\*)$"
max_bytes: 128
- ignore_empty: false
},
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {description: "Identifier of the tenant, if you are not using multi-tenancy (have only one tenant) use pre-inserted tenant t1 for this field. Required, and must match the pattern \\“[a-zA-Z0-9-,]+\\“, max 64 bytes."}
];
@@ -2907,13 +2868,13 @@ message DataDeleteRequest {
// tuple_filter specifies the criteria used to select the tuples that should be deleted.
TupleFilter tuple_filter = 2 [
json_name = "tuple_filter",
- (validate.rules).message.required = true
+ (buf.validate.field).required = true
];
// attribute_filter specifies the criteria used to select the attributes that should be deleted.
AttributeFilter attribute_filter = 3 [
json_name = "attribute_filter",
- (validate.rules).message.required = true
+ (buf.validate.field).required = true
];
}
@@ -2931,10 +2892,9 @@ message DataDeleteResponse {
message RelationshipDeleteRequest {
string tenant_id = 1 [
json_name = "tenant_id",
- (validate.rules).string = {
+ (buf.validate.field).string = {
pattern: "^([a-zA-Z0-9_\\-@\\.:+]{1,128}|\\*)$"
max_bytes: 128
- ignore_empty: false
},
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {description: "Identifier of the tenant, if you are not using multi-tenancy (have only one tenant) use pre-inserted tenant t1 for this field. Required, and must match the pattern \\“[a-zA-Z0-9-,]+\\“, max 64 bytes."}
];
@@ -2955,10 +2915,9 @@ message RelationshipDeleteResponse {
message BundleRunRequest {
string tenant_id = 1 [
json_name = "tenant_id",
- (validate.rules).string = {
+ (buf.validate.field).string = {
pattern: "^([a-zA-Z0-9_\\-@\\.:+]{1,128}|\\*)$"
max_bytes: 128
- ignore_empty: false
},
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {description: "Identifier of the tenant, if you are not using multi-tenancy (have only one tenant) use pre-inserted tenant t1 for this field. Required, and must match the pattern \\“[a-zA-Z0-9-,]+\\“, max 64 bytes."}
];
@@ -3309,10 +3268,9 @@ service Bundle {
message BundleWriteRequest {
string tenant_id = 1 [
json_name = "tenant_id",
- (validate.rules).string = {
+ (buf.validate.field).string = {
pattern: "^([a-zA-Z0-9_\\-@\\.:+]{1,128}|\\*)$"
max_bytes: 128
- ignore_empty: false
},
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {description: "Identifier of the tenant, if you are not using multi-tenancy (have only one tenant) use pre-inserted tenant t1 for this field. Required, and must match the pattern \\“[a-zA-Z0-9-,]+\\“, max 64 bytes."}
];
@@ -3329,10 +3287,9 @@ message BundleWriteResponse {
message BundleReadRequest {
string tenant_id = 1 [
json_name = "tenant_id",
- (validate.rules).string = {
+ (buf.validate.field).string = {
pattern: "^([a-zA-Z0-9_\\-@\\.:+]{1,128}|\\*)$"
max_bytes: 128
- ignore_empty: false
},
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {description: "Identifier of the tenant, if you are not using multi-tenancy (have only one tenant) use pre-inserted tenant t1 for this field. Required, and must match the pattern \\“[a-zA-Z0-9-,]+\\“, max 64 bytes."}
];
@@ -3349,10 +3306,9 @@ message BundleReadResponse {
message BundleDeleteRequest {
string tenant_id = 1 [
json_name = "tenant_id",
- (validate.rules).string = {
+ (buf.validate.field).string = {
pattern: "^([a-zA-Z0-9_\\-@\\.:+]{1,128}|\\*)$"
max_bytes: 128
- ignore_empty: false
},
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {description: "Identifier of the tenant, if you are not using multi-tenancy (have only one tenant) use pre-inserted tenant t1 for this field. Required, and must match the pattern \\“[a-zA-Z0-9-,]+\\“, max 64 bytes."}
];
@@ -3636,20 +3592,16 @@ message TenantCreateRequest {
// id is a unique identifier for the tenant.
string id = 1 [
json_name = "id",
- (validate.rules).string = {
+ (buf.validate.field).string = {
pattern: "[a-zA-Z0-9-,]+"
max_bytes: 64
- ignore_empty: false
}
];
// name is the name of the tenant.
string name = 2 [
json_name = "name",
- (validate.rules).string = {
- max_bytes: 64
- ignore_empty: false
- }
+ (buf.validate.field).string = {max_bytes: 64}
];
}
@@ -3664,7 +3616,7 @@ message TenantDeleteRequest {
// id is the unique identifier of the tenant to be deleted.
string id = 1 [
json_name = "id",
- (validate.rules).string = {ignore_empty: false}
+ (buf.validate.field).string = {}
];
}
@@ -3680,17 +3632,16 @@ message TenantListRequest {
// The value should be between 1 and 100.
uint32 page_size = 1 [
json_name = "page_size",
- (validate.rules).uint32 = {
- gte: 1
- ignore_empty: true
- }
+ (buf.validate.field).uint32 = {gte: 1},
+ (buf.validate.field).ignore = IGNORE_IF_ZERO_VALUE
];
// continuous_token is an optional parameter used for pagination.
// It should be the value received in the previous response.
string continuous_token = 2 [
json_name = "continuous_token",
- (validate.rules).string = {ignore_empty: true}
+ (buf.validate.field).string = {},
+ (buf.validate.field).ignore = IGNORE_IF_ZERO_VALUE
];
}
diff --git a/proto/buf.lock b/proto/buf.lock
index c7e976072..2bdb6cb3d 100644
--- a/proto/buf.lock
+++ b/proto/buf.lock
@@ -1,18 +1,12 @@
# Generated by buf. DO NOT EDIT.
-version: v1
+version: v2
deps:
- - remote: buf.build
- owner: envoyproxy
- repository: protoc-gen-validate
- commit: daf171c6cdb54629b5f51e345a79e4dd
- digest: shake256:4ae167d7eed10da5f83a3f5df8c670d249170f11b1f2fd19afda06be2cff4d47dcc95e9e4a15151ecc8ce2d3d3614caf9a04d3ad82fb768a3870dedfa9455f36
- - remote: buf.build
- owner: googleapis
- repository: googleapis
+ - name: buf.build/bufbuild/protovalidate
+ commit: 511051f7f4374c3ca873b53ae68a9288
+ digest: b5:a4a2d4d808a25984cced60769c822c5d496ef0b740f56ac0c9e6b97aaa25b86a9332a00ffd74e0cd202be29e91bd3edfb0bf2ba4dacfe48ff2d8217f9986e3c8
+ - name: buf.build/googleapis/googleapis
commit: 61b203b9a9164be9a834f58c37be6f62
- digest: shake256:e619113001d6e284ee8a92b1561e5d4ea89a47b28bf0410815cb2fa23914df8be9f1a6a98dcf069f5bc2d829a2cfb1ac614863be45cd4f8a5ad8606c5f200224
- - remote: buf.build
- owner: grpc-ecosystem
- repository: grpc-gateway
+ digest: b5:7811a98b35bd2e4ae5c3ac73c8b3d9ae429f3a790da15de188dc98fc2b77d6bb10e45711f14903af9553fa9821dff256054f2e4b7795789265bc476bec2f088c
+ - name: buf.build/grpc-ecosystem/grpc-gateway
commit: 4c5ba75caaf84e928b7137ae5c18c26a
- digest: shake256:e174ad9408f3e608f6157907153ffec8d310783ee354f821f57178ffbeeb8faa6bb70b41b61099c1783c82fe16210ebd1279bc9c9ee6da5cffba9f0e675b8b99
+ digest: b5:c113e62fb3b29289af785866cae062b55ec8ae19ab3f08f3004098928fbca657730a06810b2012951294326b95669547194fa84476b9e9b688d4f8bf77a0691d
diff --git a/proto/buf.yaml b/proto/buf.yaml
index 18024efc4..bcf2d7ec2 100644
--- a/proto/buf.yaml
+++ b/proto/buf.yaml
@@ -1,14 +1,20 @@
-version: v1
-name: buf.build/permifyco/permify
+version: v2
+modules:
+ - path: .
+ name: buf.build/permifyco/permify
deps:
- - buf.build/envoyproxy/protoc-gen-validate:daf171c6cdb54629b5f51e345a79e4dd
- - buf.build/grpc-ecosystem/grpc-gateway:4c5ba75caaf84e928b7137ae5c18c26a
+ - buf.build/bufbuild/protovalidate
- buf.build/googleapis/googleapis:61b203b9a9164be9a834f58c37be6f62
-breaking:
- ignore_unstable_packages: true
+ - buf.build/grpc-ecosystem/grpc-gateway:4c5ba75caaf84e928b7137ae5c18c26a
lint:
- allow_comment_ignores: true
except:
- - PACKAGE_VERSION_SUFFIX
- FIELD_LOWER_SNAKE_CASE
- - SERVICE_SUFFIX
\ No newline at end of file
+ - FIELD_NOT_REQUIRED
+ - PACKAGE_NO_IMPORT_CYCLE
+ - PACKAGE_VERSION_SUFFIX
+ - SERVICE_SUFFIX
+breaking:
+ except:
+ - EXTENSION_NO_DELETE
+ - FIELD_SAME_DEFAULT
+ ignore_unstable_packages: true
diff --git a/sdk/go/grpc/main.go b/sdk/go/grpc/main.go
index 1c8c25425..3b31038bf 100644
--- a/sdk/go/grpc/main.go
+++ b/sdk/go/grpc/main.go
@@ -4,10 +4,11 @@ import (
"context"
"log"
- "buf.build/gen/go/permifyco/permify/protocolbuffers/go/base/v1"
- pclient "github.com/Permify/permify-go/grpc"
"google.golang.org/grpc"
"google.golang.org/grpc/credentials/insecure"
+ "buf.build/gen/go/permifyco/permify/protocolbuffers/go/base/v1"
+
+ pclient "github.com/Permify/permify-go/grpc"
)
func main() {