From 4046325ca09e5681cbdcb2081c50658dd1d16462 Mon Sep 17 00:00:00 2001 From: Tanner Stirrat Date: Thu, 21 Nov 2024 13:39:15 -0700 Subject: [PATCH 1/7] Use protovalidate instead of protoc-gen-validate, move to v2 --- buf.lock | 17 +++++++---------- buf.yaml | 11 ++++++++--- 2 files changed, 15 insertions(+), 13 deletions(-) diff --git a/buf.lock b/buf.lock index ee3653b..e098f10 100644 --- a/buf.lock +++ b/buf.lock @@ -1,15 +1,12 @@ # Generated by buf. DO NOT EDIT. -version: v1 +version: v2 deps: - - remote: buf.build - owner: envoyproxy - repository: protoc-gen-validate + - name: buf.build/envoyproxy/protoc-gen-validate commit: 45685e052c7e406b9fbd441fc7a568a5 - - remote: buf.build - owner: googleapis - repository: googleapis + digest: b5:63939effe0c64a94cd3151770b73007e43c9aeff31dcb24737fb11750dcaaca99338df3c1e5513828a685c743712e59ce283e046c27725e96928d200492bb6ec + - name: buf.build/googleapis/googleapis commit: 62f35d8aed1149c291d606d958a7ce32 - - remote: buf.build - owner: grpc-ecosystem - repository: grpc-gateway + digest: b5:d66bf04adc77a0870bdc9328aaf887c7188a36fb02b83a480dc45ef9dc031b4d39fc6e9dc6435120ccf4fe5bfd5c6cb6592533c6c316595571f9a31420ab47fe + - name: buf.build/grpc-ecosystem/grpc-gateway commit: bc28b723cd774c32b6fbc77621518765 + digest: b5:a613f827fa6ff35a4f5e87e80e35ac6b35e5792cc9c5a658351072777d88c6d4df785a0c14889090db11667cf5463d122c7193b3719c7861d3e5747c22ce1381 diff --git a/buf.yaml b/buf.yaml index 04ec9a0..ad6a3f7 100644 --- a/buf.yaml +++ b/buf.yaml @@ -1,15 +1,20 @@ --- -version: "v1" +version: "v2" name: "buf.build/authzed/api" deps: - - "buf.build/envoyproxy/protoc-gen-validate" + - "buf.build/bufbuild/protovalidate" - "buf.build/googleapis/googleapis" - "buf.build/grpc-ecosystem/grpc-gateway" lint: except: + - "FIELD_NOT_REQUIRED" + - "PACKAGE_NO_IMPORT_CYCLE" - "PACKAGE_VERSION_SUFFIX" ignore: - - "authzed/api/v0" # legacy from before we used buf + - "authzed/api/v0" + disallow_comment_ignores: true breaking: use: - "WIRE_JSON" + except: + - "FIELD_SAME_DEFAULT" From 90fb5bc48398c2a40915ff71d8a19209ba2170da Mon Sep 17 00:00:00 2001 From: Tanner Stirrat Date: Thu, 21 Nov 2024 13:41:52 -0700 Subject: [PATCH 2/7] Run buf format Migrate files and re-add old validate temporarily --- .pre-commit-config.yaml | 2 +- .../api/materialize/v0/watchpermissions.proto | 2 +- .../materialize/v0/watchpermissionsets.proto | 28 +- authzed/api/v0/core.proto | 94 ++- authzed/api/v0/developer.proto | 6 +- authzed/api/v1/core.proto | 170 +++-- authzed/api/v1/debug.proto | 45 +- authzed/api/v1/error_reason.proto | 50 +- authzed/api/v1/experimental_service.proto | 303 ++++++--- authzed/api/v1/openapi.proto | 81 ++- authzed/api/v1/permission_service.proto | 638 ++++++++++++------ authzed/api/v1/schema_service.proto | 29 +- authzed/api/v1/watch_service.proto | 30 +- authzed/api/v1alpha1/schema.proto | 28 +- .../api/v1alpha1/watchresources_service.proto | 54 +- buf.lock | 15 +- buf.yaml | 1 + 17 files changed, 1086 insertions(+), 490 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index a36919c..584b2eb 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,7 +1,7 @@ --- repos: - repo: "https://github.com/bufbuild/buf" - rev: "v1.6.0" + rev: "v1.47.2" hooks: - id: "buf-lint" - repo: "https://github.com/adrienverge/yamllint.git" diff --git a/authzed/api/materialize/v0/watchpermissions.proto b/authzed/api/materialize/v0/watchpermissions.proto index a55a435..dff0499 100644 --- a/authzed/api/materialize/v0/watchpermissions.proto +++ b/authzed/api/materialize/v0/watchpermissions.proto @@ -4,8 +4,8 @@ package authzed.api.materialize.v0; import "authzed/api/v1/core.proto"; option go_package = "github.com/authzed/authzed-go/proto/authzed/api/materialize/v0"; -option java_package = "com.authzed.api.materialize.v0"; option java_multiple_files = true; +option java_package = "com.authzed.api.materialize.v0"; service WatchPermissionsService { // WatchPermissions returns a stream of PermissionChange events for the given permissions. diff --git a/authzed/api/materialize/v0/watchpermissionsets.proto b/authzed/api/materialize/v0/watchpermissionsets.proto index 6d68e35..079a21d 100644 --- a/authzed/api/materialize/v0/watchpermissionsets.proto +++ b/authzed/api/materialize/v0/watchpermissionsets.proto @@ -4,8 +4,8 @@ package authzed.api.materialize.v0; import "authzed/api/v1/core.proto"; option go_package = "github.com/authzed/authzed-go/proto/authzed/api/materialize/v0"; -option java_package = "com.authzed.api.materialize.v0"; option java_multiple_files = true; +option java_package = "com.authzed.api.materialize.v0"; service WatchPermissionSetsService { // WatchPermissionSets returns a stream of changes to the sets which can be used to compute the watched permissions. @@ -55,7 +55,7 @@ service WatchPermissionSetsService { // and the revision token from the last LookupPermissionSets response. rpc LookupPermissionSets(LookupPermissionSetsRequest) returns (stream LookupPermissionSetsResponse) {} } - + message WatchPermissionSetsRequest { // optional_starting_after is used to specify the SpiceDB revision to start watching from. // If not specified, the watch will start from the current SpiceDB revision time of the request ("head revision"). @@ -154,21 +154,21 @@ message PermissionSetChange { } message SetReference { - // object_type is the type of object in a permission set - string object_type = 1; - // object_id is the ID of a permission set - string object_id = 2; - // permission_or_relation is the permission or relation referenced by this permission set - string permission_or_relation = 3; + // object_type is the type of object in a permission set + string object_type = 1; + // object_id is the ID of a permission set + string object_id = 2; + // permission_or_relation is the permission or relation referenced by this permission set + string permission_or_relation = 3; } message MemberReference { - // object_type is the type of object of a permission set member - string object_type = 1; - // object_id is the ID of a permission set member - string object_id = 2; - // optional_permission_or_relation is the permission or relation referenced by this permission set member - string optional_permission_or_relation = 3; + // object_type is the type of object of a permission set member + string object_type = 1; + // object_id is the ID of a permission set member + string object_id = 2; + // optional_permission_or_relation is the permission or relation referenced by this permission set member + string optional_permission_or_relation = 3; } // LookupPermissionSetsRequired is a signal that the consumer should perform a LookupPermissionSets call because diff --git a/authzed/api/v0/core.proto b/authzed/api/v0/core.proto index 7ff2dce..6325396 100644 --- a/authzed/api/v0/core.proto +++ b/authzed/api/v0/core.proto @@ -1,11 +1,12 @@ syntax = "proto3"; package authzed.api.v0; +import "buf/validate/validate.proto"; +import "validate/validate.proto"; + option go_package = "github.com/authzed/authzed-go/proto/authzed/api/v0"; option java_package = "com.authzed.api.v0"; -import "validate/validate.proto"; - message RelationTuple { // Each tupleset specifies keys of a set of relation tuples. The set can // include a single tuple key, or all tuples with a given object ID or @@ -18,41 +19,80 @@ message RelationTuple { // doc:12345#writer#* (all tuples with direct write relationship with the // document) doc:#writer#group:eng#member (all tuples that eng group has write // relationship) - ObjectAndRelation object_and_relation = 1 - [ (validate.rules).message.required = true ]; - User user = 2 [ (validate.rules).message.required = true ]; + ObjectAndRelation object_and_relation = 1 [ + (validate.rules).message.required = true, + (buf.validate.field).required = true + ]; + User user = 2 [ + (validate.rules).message.required = true, + (buf.validate.field).required = true + ]; } message ObjectAndRelation { - string namespace = 1 [ (validate.rules).string = { - pattern : "^([a-z][a-z0-9_]{1,61}[a-z0-9]/)?[a-z][a-z0-9_]{1,62}[a-z0-9]$", - max_bytes : 128, - } ]; - string object_id = 2 [ (validate.rules).string = { - pattern : "^(([a-zA-Z0-9_][a-zA-Z0-9/_|-]{0,127})|\\*)$", - max_bytes : 128, - } ]; - string relation = 3 [ (validate.rules).string = { - pattern : "^(\\.\\.\\.|[a-z][a-z0-9_]{1,62}[a-z0-9])$", - max_bytes : 64, - } ]; + string namespace = 1 [ + (validate.rules).string = { + pattern: "^([a-z][a-z0-9_]{1,61}[a-z0-9]/)?[a-z][a-z0-9_]{1,62}[a-z0-9]$" + max_bytes: 128 + }, + (buf.validate.field).string = { + pattern: "^([a-z][a-z0-9_]{1,61}[a-z0-9]/)?[a-z][a-z0-9_]{1,62}[a-z0-9]$" + max_bytes: 128 + } + ]; + string object_id = 2 [ + (validate.rules).string = { + pattern: "^(([a-zA-Z0-9_][a-zA-Z0-9/_|-]{0,127})|\\*)$" + max_bytes: 128 + }, + (buf.validate.field).string = { + pattern: "^(([a-zA-Z0-9_][a-zA-Z0-9/_|-]{0,127})|\\*)$" + max_bytes: 128 + } + ]; + string relation = 3 [ + (validate.rules).string = { + pattern: "^(\\.\\.\\.|[a-z][a-z0-9_]{1,62}[a-z0-9])$" + max_bytes: 64 + }, + (buf.validate.field).string = { + pattern: "^(\\.\\.\\.|[a-z][a-z0-9_]{1,62}[a-z0-9])$" + max_bytes: 64 + } + ]; } message RelationReference { - string namespace = 1 [ (validate.rules).string = { - pattern : "^([a-z][a-z0-9_]{1,61}[a-z0-9]/)?[a-z][a-z0-9_]{1,62}[a-z0-9]$", - max_bytes : 128, - } ]; - string relation = 3 [ (validate.rules).string = { - pattern : "^(\\.\\.\\.|[a-z][a-z0-9_]{1,62}[a-z0-9])$", - max_bytes : 64, - } ]; + string namespace = 1 [ + (validate.rules).string = { + pattern: "^([a-z][a-z0-9_]{1,61}[a-z0-9]/)?[a-z][a-z0-9_]{1,62}[a-z0-9]$" + max_bytes: 128 + }, + (buf.validate.field).string = { + pattern: "^([a-z][a-z0-9_]{1,61}[a-z0-9]/)?[a-z][a-z0-9_]{1,62}[a-z0-9]$" + max_bytes: 128 + } + ]; + string relation = 3 [ + (validate.rules).string = { + pattern: "^(\\.\\.\\.|[a-z][a-z0-9_]{1,62}[a-z0-9])$" + max_bytes: 64 + }, + (buf.validate.field).string = { + pattern: "^(\\.\\.\\.|[a-z][a-z0-9_]{1,62}[a-z0-9])$" + max_bytes: 64 + } + ]; } message User { oneof user_oneof { option (validate.required) = true; + option (buf.validate.oneof).required = true; - ObjectAndRelation userset = 2 [ (validate.rules).message.required = true ]; + ObjectAndRelation userset = 2 [ + (validate.rules).message.required = true, + (buf.validate.field).required = true + ]; } -} \ No newline at end of file +} diff --git a/authzed/api/v0/developer.proto b/authzed/api/v0/developer.proto index 9a4b97d..ab9828c 100644 --- a/authzed/api/v0/developer.proto +++ b/authzed/api/v0/developer.proto @@ -1,11 +1,11 @@ syntax = "proto3"; package authzed.api.v0; +import "authzed/api/v0/core.proto"; + option go_package = "github.com/authzed/authzed-go/proto/authzed/api/v0"; option java_package = "com.authzed.api.v0"; -import "authzed/api/v0/core.proto"; - service DeveloperService { rpc EditCheck(EditCheckRequest) returns (EditCheckResponse) {} rpc Validate(ValidateRequest) returns (ValidateResponse) {} @@ -126,7 +126,7 @@ message DeveloperError { uint32 column = 3; Source source = 4; ErrorKind kind = 5; - + repeated string path = 6; // context holds the context for the error. For schema issues, this will be the diff --git a/authzed/api/v1/core.proto b/authzed/api/v1/core.proto index d6cb44a..314fcf4 100644 --- a/authzed/api/v1/core.proto +++ b/authzed/api/v1/core.proto @@ -1,35 +1,63 @@ syntax = "proto3"; package authzed.api.v1; +import "buf/validate/validate.proto"; +import "google/protobuf/struct.proto"; +import "validate/validate.proto"; + option go_package = "github.com/authzed/authzed-go/proto/authzed/api/v1"; +option java_multiple_files = true; option java_package = "com.authzed.api.v1"; option java_multiple_files = true; import "google/protobuf/struct.proto"; import "google/protobuf/timestamp.proto"; import "validate/validate.proto"; +option java_multiple_files = true; + +import "google/protobuf/struct.proto"; +import "validate/validate.proto"; // Relationship specifies how a resource relates to a subject. Relationships // form the data for the graph over which all permissions questions are // answered. message Relationship { // resource is the resource to which the subject is related, in some manner - ObjectReference resource = 1 [ (validate.rules).message.required = true ]; + ObjectReference resource = 1 [ + (validate.rules).message.required = true, + (buf.validate.field).required = true + ]; // relation is how the resource and subject are related. - string relation = 2 [ (validate.rules).string = { - pattern : "^[a-z][a-z0-9_]{1,62}[a-z0-9]$", - max_bytes : 64, - } ]; + string relation = 2 [ + (validate.rules).string = { + pattern: "^[a-z][a-z0-9_]{1,62}[a-z0-9]$" + max_bytes: 64 + }, + (buf.validate.field).string = { + pattern: "^[a-z][a-z0-9_]{1,62}[a-z0-9]$" + max_bytes: 64 + } + ]; // subject is the subject to which the resource is related, in some manner. - SubjectReference subject = 3 [ (validate.rules).message.required = true ]; + SubjectReference subject = 3 [ + (validate.rules).message.required = true, + (buf.validate.field).required = true + ]; // optional_caveat is a reference to a the caveat that must be enforced over the relationship. ContextualizedCaveat optional_caveat = 4 [ (validate.rules).message.required = false ]; // optional_expires_at is the time at which the relationship expires, if any. google.protobuf.Timestamp optional_expires_at = 5; + // optional_caveat is a reference to a the caveat that must be enforced over the relationship + ContextualizedCaveat optional_caveat = 4 [ (validate.rules).message.required = false ]; + // optional_caveat is a reference to a the caveat that must be enforced over the relationship + ContextualizedCaveat optional_caveat = 4 [ + (validate.rules).message.required = false, + (buf.validate.field).required = false + ]; } // ContextualizedCaveat represents a reference to a caveat to be used by caveated relationships. @@ -37,36 +65,66 @@ message Relationship { // The keys must match the arguments defined on the caveat in the schema. message ContextualizedCaveat { // caveat_name is the name of the caveat expression to use, as defined in the schema - string caveat_name = 1 [ (validate.rules).string = { - pattern : "^([a-zA-Z0-9_][a-zA-Z0-9/_|-]{0,127})$", - max_bytes : 128, - } ]; + string caveat_name = 1 [ + (validate.rules).string = { + pattern: "^([a-zA-Z0-9_][a-zA-Z0-9/_|-]{0,127})$" + max_bytes: 128 + }, + (buf.validate.field).string = { + pattern: "^([a-zA-Z0-9_][a-zA-Z0-9/_|-]{0,127})$" + max_bytes: 128 + } + ]; // context consists of any named values that are defined at write time for the caveat expression - google.protobuf.Struct context = 2 [ (validate.rules).message.required = false ]; + google.protobuf.Struct context = 2 [ + (validate.rules).message.required = false, + (buf.validate.field).required = false + ]; } // SubjectReference is used for referring to the subject portion of a // Relationship. The relation component is optional and is used for defining a // sub-relation on the subject, e.g. group:123#members message SubjectReference { - ObjectReference object = 1 [ (validate.rules).message.required = true ]; - string optional_relation = 2 [ (validate.rules).string = { - pattern : "^([a-z][a-z0-9_]{1,62}[a-z0-9])?$", - max_bytes : 64, - } ]; + ObjectReference object = 1 [ + (validate.rules).message.required = true, + (buf.validate.field).required = true + ]; + string optional_relation = 2 [ + (validate.rules).string = { + pattern: "^([a-z][a-z0-9_]{1,62}[a-z0-9])?$" + max_bytes: 64 + }, + (buf.validate.field).string = { + pattern: "^([a-z][a-z0-9_]{1,62}[a-z0-9])?$" + max_bytes: 64 + } + ]; } // ObjectReference is used to refer to a specific object in the system. message ObjectReference { - string object_type = 1 [ (validate.rules).string = { - pattern : "^([a-z][a-z0-9_]{1,61}[a-z0-9]/)*[a-z][a-z0-9_]{1,62}[a-z0-9]$", - max_bytes : 128, - } ]; - string object_id = 2 [ (validate.rules).string = { - pattern : "^(([a-zA-Z0-9/_|\\-=+]{1,})|\\*)$", - max_bytes : 1024, - } ]; + string object_type = 1 [ + (validate.rules).string = { + pattern: "^([a-z][a-z0-9_]{1,61}[a-z0-9]/)*[a-z][a-z0-9_]{1,62}[a-z0-9]$" + max_bytes: 128 + }, + (buf.validate.field).string = { + pattern: "^([a-z][a-z0-9_]{1,61}[a-z0-9]/)*[a-z][a-z0-9_]{1,62}[a-z0-9]$" + max_bytes: 128 + } + ]; + string object_id = 2 [ + (validate.rules).string = { + pattern: "^(([a-zA-Z0-9/_|\\-=+]{1,})|\\*)$" + max_bytes: 1024 + }, + (buf.validate.field).string = { + pattern: "^(([a-zA-Z0-9/_|\\-=+]{1,})|\\*)$" + max_bytes: 1024 + } + ]; } // ZedToken is used to provide causality metadata between Write and Check @@ -74,21 +132,27 @@ message ObjectReference { // // See the authzed.api.v1.Consistency message for more information. message ZedToken { - string token = 1 [ (validate.rules).string = { - min_bytes : 1, - } ]; + string token = 1 [ + (validate.rules).string = {min_bytes: 1}, + (buf.validate.field).string = {min_bytes: 1} + ]; } // Cursor is used to provide resumption of listing between calls to APIs // such as LookupResources. message Cursor { - string token = 1 [ (validate.rules).string = { - min_bytes : 1, - max_bytes : 102400, - } ]; + string token = 1 [ + (validate.rules).string = { + min_bytes: 1 + max_bytes: 102400 + }, + (buf.validate.field).string = { + min_bytes: 1 + max_bytes: 102400 + } + ]; } - // RelationshipUpdate is used for mutating a single relationship within the // service. // @@ -107,8 +171,20 @@ message RelationshipUpdate { OPERATION_TOUCH = 2; OPERATION_DELETE = 3; } - Operation operation = 1 [ (validate.rules).enum = {defined_only: true, not_in: [0]} ]; - Relationship relationship = 2 [ (validate.rules).message.required = true ]; + Operation operation = 1 [ + (validate.rules).enum = { + defined_only: true + not_in: [0] + }, + (buf.validate.field).enum = { + defined_only: true + not_in: [0] + } + ]; + Relationship relationship = 2 [ + (validate.rules).message.required = true, + (buf.validate.field).required = true + ]; } // PermissionRelationshipTree is used for representing a tree of a resource and @@ -116,6 +192,7 @@ message RelationshipUpdate { message PermissionRelationshipTree { oneof tree_type { option (validate.required) = true; + option (buf.validate.oneof).required = true; AlgebraicSubjectSet intermediate = 1; DirectSubjectSet leaf = 2; @@ -142,17 +219,34 @@ message AlgebraicSubjectSet { OPERATION_EXCLUSION = 3; } - Operation operation = 1 [ (validate.rules).enum = {defined_only: true, not_in: [0]} ]; - repeated PermissionRelationshipTree children = 2 [ (validate.rules).repeated.items.message.required = true ]; + Operation operation = 1 [ + (validate.rules).enum = { + defined_only: true + not_in: [0] + }, + (buf.validate.field).enum = { + defined_only: true + not_in: [0] + } + ]; + repeated PermissionRelationshipTree children = 2 [ + (validate.rules).repeated.items.message.required = true, + (buf.validate.field).repeated.items.required = true + ]; } // DirectSubjectSet is a subject set which is simply a collection of subjects. -message DirectSubjectSet { repeated SubjectReference subjects = 1; } +message DirectSubjectSet { + repeated SubjectReference subjects = 1; +} // PartialCaveatInfo carries information necessary for the client to take action // in the event a response contains a partially evaluated caveat message PartialCaveatInfo { // missing_required_context is a list of one or more fields that were missing and prevented caveats // from being fully evaluated - repeated string missing_required_context = 1 [(validate.rules).repeated.min_items = 1]; + repeated string missing_required_context = 1 [ + (validate.rules).repeated.min_items = 1, + (buf.validate.field).repeated.min_items = 1 + ]; } diff --git a/authzed/api/v1/debug.proto b/authzed/api/v1/debug.proto index ad06688..6bdbe37 100644 --- a/authzed/api/v1/debug.proto +++ b/authzed/api/v1/debug.proto @@ -2,14 +2,19 @@ syntax = "proto3"; package authzed.api.v1; import "authzed/api/v1/core.proto"; +import "buf/validate/validate.proto"; +import "google/protobuf/duration.proto"; +import "google/protobuf/struct.proto"; import "validate/validate.proto"; import "google/protobuf/struct.proto"; import "google/protobuf/duration.proto"; import "google/protobuf/timestamp.proto"; +import "google/protobuf/struct.proto"; +import "google/protobuf/duration.proto"; option go_package = "github.com/authzed/authzed-go/proto/authzed/api/v1"; -option java_package = "com.authzed.api.v1"; option java_multiple_files = true; +option java_package = "com.authzed.api.v1"; // DebugInformation defines debug information returned by an API call in a footer when // requested with a specific debugging header. @@ -48,21 +53,46 @@ message CheckDebugTrace { // resource holds the resource on which the Check was performed. // for batched calls, the object_id field contains a comma-separated list of object IDs // for all the resources checked in the batch. - ObjectReference resource = 1 [ (validate.rules).message.required = true ]; + ObjectReference resource = 1 [(validate.rules).message.required = true]; + ObjectReference resource = 1 [ + (validate.rules).message.required = true, + (buf.validate.field).required = true + ]; // permission holds the name of the permission or relation on which the Check was performed. string permission = 2; // permission_type holds information indicating whether it was a permission or relation. - PermissionType permission_type = 3 [ (validate.rules).enum = {defined_only: true, not_in: [0]} ]; + PermissionType permission_type = 3 [ + (validate.rules).enum = { + defined_only: true + not_in: [0] + }, + (buf.validate.field).enum = { + defined_only: true + not_in: [0] + } + ]; // subject holds the subject on which the Check was performed. This will be static across all calls within // the same Check tree. - SubjectReference subject = 4 [ (validate.rules).message.required = true ]; + SubjectReference subject = 4 [ + (validate.rules).message.required = true, + (buf.validate.field).required = true + ]; // result holds the result of the Check call. - Permissionship result = 5 [ (validate.rules).enum = {defined_only: true, not_in: [0]} ]; - + Permissionship result = 5 [ + (validate.rules).enum = { + defined_only: true + not_in: [0] + }, + (buf.validate.field).enum = { + defined_only: true + not_in: [0] + } + ]; + // caveat_evaluation_info holds information about the caveat evaluated for this step of the trace. CaveatEvalInfo caveat_evaluation_info = 8; @@ -72,6 +102,7 @@ message CheckDebugTrace { // resolution holds information about how the problem was resolved. oneof resolution { option (validate.required) = true; + option (buf.validate.oneof).required = true; // was_cached_result, if true, indicates that the result was found in the cache and returned directly. bool was_cached_result = 6; @@ -127,4 +158,4 @@ message CaveatEvalInfo { // caveat_name is the name of the caveat that was executed, if applicable. string caveat_name = 5; -} \ No newline at end of file +} diff --git a/authzed/api/v1/error_reason.proto b/authzed/api/v1/error_reason.proto index c1ced48..ec1baf3 100644 --- a/authzed/api/v1/error_reason.proto +++ b/authzed/api/v1/error_reason.proto @@ -2,8 +2,8 @@ syntax = "proto3"; package authzed.api.v1; option go_package = "github.com/authzed/authzed-go/proto/authzed/api/v1"; -option java_package = "com.authzed.api.v1"; option java_multiple_files = true; +option java_package = "com.authzed.api.v1"; // Defines the supported values for `google.rpc.ErrorInfo.reason` for the // `authzed.com` error domain. @@ -15,7 +15,7 @@ enum ErrorReason { // // Example of an ErrorInfo: // - // { + // { // "reason": "ERROR_REASON_SCHEMA_PARSE_ERROR", // "domain": "authzed.com", // "metadata": { @@ -34,7 +34,7 @@ enum ErrorReason { // // Example of an ErrorInfo: // - // { + // { // "reason": "ERROR_REASON_SCHEMA_TYPE_ERROR", // "domain": "authzed.com", // "metadata": { @@ -48,7 +48,7 @@ enum ErrorReason { // // Example of an ErrorInfo: // - // { + // { // "reason": "ERROR_REASON_UNKNOWN_DEFINITION", // "domain": "authzed.com", // "metadata": { @@ -61,7 +61,7 @@ enum ErrorReason { // // Example of an ErrorInfo: // - // { + // { // "reason": "ERROR_REASON_UNKNOWN_RELATION_OR_PERMISSION", // "domain": "authzed.com", // "metadata": { @@ -88,7 +88,7 @@ enum ErrorReason { // // Example of an ErrorInfo: // - // { + // { // "reason": "ERROR_REASON_TOO_MANY_PRECONDITIONS_IN_REQUEST", // "domain": "authzed.com", // "metadata": { @@ -102,7 +102,7 @@ enum ErrorReason { // // Example of an ErrorInfo: // - // { + // { // "reason": "ERROR_REASON_WRITE_OR_DELETE_PRECONDITION_FAILURE", // "domain": "authzed.com", // "metadata": { @@ -117,7 +117,7 @@ enum ErrorReason { // // Example of an ErrorInfo: // - // { + // { // "reason": "ERROR_REASON_SERVICE_READ_ONLY", // "domain": "authzed.com" // } @@ -127,7 +127,7 @@ enum ErrorReason { // // Example of an ErrorInfo: // - // { + // { // "reason": "ERROR_REASON_UNKNOWN_CAVEAT", // "domain": "authzed.com", // "metadata": { @@ -140,7 +140,7 @@ enum ErrorReason { // // Example of an ErrorInfo: // - // { + // { // "reason": "ERROR_REASON_INVALID_SUBJECT_TYPE", // "domain": "authzed.com", // "metadata": { @@ -155,7 +155,7 @@ enum ErrorReason { // // Example of an ErrorInfo: // - // { + // { // "reason": "ERROR_REASON_CAVEAT_PARAMETER_TYPE_ERROR", // "domain": "authzed.com", // "metadata": { @@ -172,7 +172,7 @@ enum ErrorReason { // // Example of an ErrorInfo: // - // { + // { // "reason": "ERROR_REASON_UPDATES_ON_SAME_RELATIONSHIP", // "domain": "authzed.com", // "metadata": { @@ -186,7 +186,7 @@ enum ErrorReason { // // Example of an ErrorInfo: // - // { + // { // "reason": "ERROR_REASON_CANNOT_UPDATE_PERMISSION", // "domain": "authzed.com", // "metadata": { @@ -200,7 +200,7 @@ enum ErrorReason { // // Example of an ErrorInfo: // - // { + // { // "reason": "ERROR_REASON_CAVEAT_EVALUATION_ERROR", // "domain": "authzed.com", // "metadata": { @@ -213,7 +213,7 @@ enum ErrorReason { // // Example of an ErrorInfo: // - // { + // { // "reason": "ERROR_REASON_INVALID_CURSOR", // "domain": "authzed.com", // "metadata": { @@ -228,7 +228,7 @@ enum ErrorReason { // // Example of an ErrorInfo: // - // { + // { // "reason": "ERROR_REASON_TOO_MANY_RELATIONSHIPS_FOR_TRANSACTIONAL_DELETE", // "domain": "authzed.com", // "metadata": { @@ -305,7 +305,7 @@ enum ErrorReason { // // Example of an ErrorInfo: // - // { + // { // "reason": "ERROR_REASON_TOO_MANY_CHECKS_IN_REQUEST", // "domain": "authzed.com", // "metadata": { @@ -319,7 +319,7 @@ enum ErrorReason { // // Example of an ErrorInfo: // - // { + // { // "reason": "ERROR_REASON_EXCEEDS_MAXIMUM_ALLOWABLE_LIMIT", // "domain": "authzed.com", // "metadata": { @@ -333,7 +333,7 @@ enum ErrorReason { // // Example of an ErrorInfo: // - // { + // { // "reason": "ERROR_REASON_INVALID_FILTER", // "domain": "authzed.com", // "metadata": { @@ -347,7 +347,7 @@ enum ErrorReason { // // Example of an ErrorInfo: // - // { + // { // "reason": "ERROR_REASON_INMEMORY_TOO_MANY_CONCURRENT_UPDATES", // "domain": "authzed.com", // "metadata": {} @@ -358,7 +358,7 @@ enum ErrorReason { // // Example of an ErrorInfo: // - // { + // { // "reason": "ERROR_REASON_EMPTY_PRECONDITION", // "domain": "authzed.com", // "metadata": {} @@ -369,7 +369,7 @@ enum ErrorReason { // // Example of an ErrorInfo: // - // { + // { // "reason": "ERROR_REASON_COUNTER_ALREADY_REGISTERED", // "domain": "authzed.com", // "metadata": { "counter_name": "name" } @@ -380,7 +380,7 @@ enum ErrorReason { // // Example of an ErrorInfo: // - // { + // { // "reason": "ERROR_REASON_COUNTER_NOT_REGISTERED", // "domain": "authzed.com", // "metadata": { "counter_name": "name" } @@ -393,7 +393,7 @@ enum ErrorReason { // // Example of an ErrorInfo: // - // { + // { // "reason": "ERROR_REASON_WILDCARD_NOT_ALLOWED", // "domain": "authzed.com", // "metadata": { "disallowed_field": "subject_id" } @@ -413,4 +413,4 @@ enum ErrorReason { // } // } ERROR_REASON_TRANSACTION_METADATA_TOO_LARGE = 29; -} \ No newline at end of file +} diff --git a/authzed/api/v1/experimental_service.proto b/authzed/api/v1/experimental_service.proto index 5f81a91..d5c482c 100644 --- a/authzed/api/v1/experimental_service.proto +++ b/authzed/api/v1/experimental_service.proto @@ -1,17 +1,17 @@ syntax = "proto3"; package authzed.api.v1; -option go_package = "github.com/authzed/authzed-go/proto/authzed/api/v1"; -option java_package = "com.authzed.api.v1"; -option java_multiple_files = true; - +import "authzed/api/v1/core.proto"; +import "authzed/api/v1/permission_service.proto"; +import "buf/validate/validate.proto"; import "google/api/annotations.proto"; -import "validate/validate.proto"; import "google/protobuf/struct.proto"; import "google/rpc/status.proto"; +import "validate/validate.proto"; -import "authzed/api/v1/core.proto"; -import "authzed/api/v1/permission_service.proto"; +option go_package = "github.com/authzed/authzed-go/proto/authzed/api/v1"; +option java_multiple_files = true; +option java_package = "com.authzed.api.v1"; // ExperimentalService exposes a number of APIs that are currently being // prototyped and tested for future inclusion in the stable API. @@ -22,48 +22,62 @@ service ExperimentalService { // to relationship sort order as possible: (resource.object_type, // resource.object_id, relation, subject.object.object_type, // subject.object.object_id, subject.optional_relation) - // + // // EXPERIMENTAL // https://github.com/authzed/spicedb/issues/1303 - rpc BulkImportRelationships(stream BulkImportRelationshipsRequest) - returns (BulkImportRelationshipsResponse) { - option (google.api.http) = { - post: "/v1/experimental/relationships/bulkimport" - body: "*" - }; - } + rpc BulkImportRelationships(stream BulkImportRelationshipsRequest) returns (BulkImportRelationshipsResponse) { + option (google.api.http) = { + post: "/v1/experimental/relationships/bulkimport" + body: "*" + }; + } // BulkExportRelationships is the fastest path available to exporting // relationships from the server. It is resumable, and will return results // in an order determined by the server. - rpc BulkExportRelationships(BulkExportRelationshipsRequest) - returns (stream BulkExportRelationshipsResponse) { - option (google.api.http) = { - post: "/v1/experimental/relationships/bulkexport" - body: "*" - }; - } + rpc BulkExportRelationships(BulkExportRelationshipsRequest) returns (stream BulkExportRelationshipsResponse) { + option (google.api.http) = { + post: "/v1/experimental/relationships/bulkexport" + body: "*" + }; + } // NOTE: BulkCheckPermission has been promoted to the stable API as "CheckBulkPermission" and the // API will be removed from experimental in a future release. - rpc BulkCheckPermission(BulkCheckPermissionRequest) - returns (BulkCheckPermissionResponse) { + rpc BulkCheckPermission(BulkCheckPermissionRequest) returns (BulkCheckPermissionResponse) { + option (google.api.http) = { + post: "/v1/experimental/permissions/bulkcheckpermission" + body: "*" + }; + option deprecated = true; + } + + // DEPRECATED: Promoted to ReflectSchema in the stable API. + rpc ExperimentalReflectSchema(ExperimentalReflectSchemaRequest) + returns (ExperimentalReflectSchemaResponse) { option (google.api.http) = { - post: "/v1/experimental/permissions/bulkcheckpermission" + post: "/v1/experimental/reflectschema" body: "*" }; option deprecated = true; } - - // DEPRECATED: Promoted to ReflectSchema in the stable API. + // EXPERIMENTAL: ReflectSchema is an API that allows clients to reflect the schema stored in + // SpiceDB. This is useful for clients that need to introspect the schema of a SpiceDB instance. rpc ExperimentalReflectSchema(ExperimentalReflectSchemaRequest) returns (ExperimentalReflectSchemaResponse) { option (google.api.http) = { post: "/v1/experimental/reflectschema" body: "*" }; - option deprecated = true; } + // EXPERIMENTAL: ReflectSchema is an API that allows clients to reflect the schema stored in + // SpiceDB. This is useful for clients that need to introspect the schema of a SpiceDB instance. + rpc ExperimentalReflectSchema(ExperimentalReflectSchemaRequest) returns (ExperimentalReflectSchemaResponse) { + option (google.api.http) = { + post: "/v1/experimental/reflectschema" + body: "*" + }; + } // DEPRECATED: Promoted to ComputablePermissions in the stable API. rpc ExperimentalComputablePermissions(ExperimentalComputablePermissionsRequest) @@ -84,6 +98,48 @@ service ExperimentalService { }; option deprecated = true; } + // EXPERIMENTAL: ComputablePermissions is an API that allows clients to request the set of + // permissions that compute based off a relation. For example, if a schema has a relation + // `viewer` and a permission `view` defined as `permission view = viewer + editor`, then the + // computable permissions for the relation `viewer` will include `view`. + rpc ExperimentalComputablePermissions(ExperimentalComputablePermissionsRequest) + returns (ExperimentalComputablePermissionsResponse) { + option (google.api.http) = { + post: "/v1/experimental/permissions/computable" + body: "*" + }; + } + + // EXPERIMENTAL: DependentRelations is an API that allows clients to request the set of + // relations and permissions that used to compute a permission, recursively. It is the + // inverse of the ComputablePermissions API. + rpc ExperimentalDependentRelations(ExperimentalDependentRelationsRequest) + returns (ExperimentalDependentRelationsResponse) { + option (google.api.http) = { + post: "/v1/experimental/permissions/dependent" + body: "*" + }; + } + // EXPERIMENTAL: ComputablePermissions is an API that allows clients to request the set of + // permissions that compute based off a relation. For example, if a schema has a relation + // `viewer` and a permission `view` defined as `permission view = viewer + editor`, then the + // computable permissions for the relation `viewer` will include `view`. + rpc ExperimentalComputablePermissions(ExperimentalComputablePermissionsRequest) returns (ExperimentalComputablePermissionsResponse) { + option (google.api.http) = { + post: "/v1/experimental/permissions/computable" + body: "*" + }; + } + + // EXPERIMENTAL: DependentRelations is an API that allows clients to request the set of + // relations and permissions that used to compute a permission, recursively. It is the + // inverse of the ComputablePermissions API. + rpc ExperimentalDependentRelations(ExperimentalDependentRelationsRequest) returns (ExperimentalDependentRelationsResponse) { + option (google.api.http) = { + post: "/v1/experimental/permissions/dependent" + body: "*" + }; + } // DEPRECATED: Promoted to DiffSchema in the stable API. rpc ExperimentalDiffSchema(ExperimentalDiffSchemaRequest) @@ -94,57 +150,87 @@ service ExperimentalService { }; option deprecated = true; } - - // EXPERIMENTAL: RegisterRelationshipCounter registers a new filter for counting relationships. A filter must be registered before - // a count can be requested. - rpc ExperimentalRegisterRelationshipCounter(ExperimentalRegisterRelationshipCounterRequest) - returns (ExperimentalRegisterRelationshipCounterResponse) { + // EXPERIMENTAL: DiffSchema is an API that allows clients to request the difference between the + // specified schema and the schema stored in SpiceDB. This is useful for clients that need to + // introspect the schema of a SpiceDB instance. + rpc ExperimentalDiffSchema(ExperimentalDiffSchemaRequest) + returns (ExperimentalDiffSchemaResponse) { option (google.api.http) = { - post: "/v1/experimental/registerrelationshipcounter" + post: "/v1/experimental/diffschema" body: "*" }; } + // EXPERIMENTAL: DiffSchema is an API that allows clients to request the difference between the + // specified schema and the schema stored in SpiceDB. This is useful for clients that need to + // introspect the schema of a SpiceDB instance. + rpc ExperimentalDiffSchema(ExperimentalDiffSchemaRequest) returns (ExperimentalDiffSchemaResponse) { + option (google.api.http) = { + post: "/v1/experimental/diffschema" + body: "*" + }; + } + + // EXPERIMENTAL: RegisterRelationshipCounter registers a new filter for counting relationships. A filter must be registered before + // a count can be requested. + rpc ExperimentalRegisterRelationshipCounter(ExperimentalRegisterRelationshipCounterRequest) returns (ExperimentalRegisterRelationshipCounterResponse) { + option (google.api.http) = { + post: "/v1/experimental/registerrelationshipcounter" + body: "*" + }; + } // EXPERIMENTAL: CountRelationships returns the count of relationships for *pre-registered* filter. - rpc ExperimentalCountRelationships(ExperimentalCountRelationshipsRequest) - returns (ExperimentalCountRelationshipsResponse) { - option (google.api.http) = { - post: "/v1/experimental/countrelationships" - body: "*" - }; - } + rpc ExperimentalCountRelationships(ExperimentalCountRelationshipsRequest) returns (ExperimentalCountRelationshipsResponse) { + option (google.api.http) = { + post: "/v1/experimental/countrelationships" + body: "*" + }; + } // EXPERIMENTAL: UnregisterRelationshipCounter unregisters an existing filter for counting relationships. - rpc ExperimentalUnregisterRelationshipCounter(ExperimentalUnregisterRelationshipCounterRequest) - returns (ExperimentalUnregisterRelationshipCounterResponse) { - option (google.api.http) = { - post: "/v1/experimental/unregisterrelationshipcounter" - body: "*" - }; + rpc ExperimentalUnregisterRelationshipCounter(ExperimentalUnregisterRelationshipCounterRequest) returns (ExperimentalUnregisterRelationshipCounterResponse) { + option (google.api.http) = { + post: "/v1/experimental/unregisterrelationshipcounter" + body: "*" + }; } } message ExperimentalRegisterRelationshipCounterRequest { // name is the name of the counter being registered. - string name = 1[ (validate.rules).string = { - pattern : "^([a-z][a-z0-9_]{1,62}[a-z0-9])?$", - max_bytes : 64, - } ]; + string name = 1 [ + (validate.rules).string = { + pattern: "^([a-z][a-z0-9_]{1,62}[a-z0-9])?$" + max_bytes: 64 + }, + (buf.validate.field).string = { + pattern: "^([a-z][a-z0-9_]{1,62}[a-z0-9])?$" + max_bytes: 64 + } + ]; // relationship_filter defines the filter to be applied to the relationships // to be counted. - RelationshipFilter relationship_filter = 2 - [ (validate.rules).message.required = true ]; + RelationshipFilter relationship_filter = 2 [ + (validate.rules).message.required = true, + (buf.validate.field).required = true + ]; } message ExperimentalRegisterRelationshipCounterResponse {} message ExperimentalCountRelationshipsRequest { // name is the name of the counter whose count is being requested. - string name = 1[ (validate.rules).string = { - pattern : "^([a-z][a-z0-9_]{1,62}[a-z0-9])?$", - max_bytes : 64, - } ]; + string name = 1 [ + (validate.rules).string = { + pattern: "^([a-z][a-z0-9_]{1,62}[a-z0-9])?$" + max_bytes: 64 + }, + (buf.validate.field).string = { + pattern: "^([a-z][a-z0-9_]{1,62}[a-z0-9])?$" + max_bytes: 64 + } + ]; } message ExperimentalCountRelationshipsResponse { @@ -162,15 +248,24 @@ message ReadCounterValue { uint64 relationship_count = 1; // read_at is the ZedToken at which the relationship count applies. - ZedToken read_at = 2 [ (validate.rules).message.required = true ]; + ZedToken read_at = 2 [ + (validate.rules).message.required = true, + (buf.validate.field).required = true + ]; } message ExperimentalUnregisterRelationshipCounterRequest { // name is the name of the counter being unregistered. - string name = 1[ (validate.rules).string = { - pattern : "^([a-z][a-z0-9_]{1,62}[a-z0-9])?$", - max_bytes : 64, - } ]; + string name = 1 [ + (validate.rules).string = { + pattern: "^([a-z][a-z0-9_]{1,62}[a-z0-9])?$" + max_bytes: 64 + }, + (buf.validate.field).string = { + pattern: "^([a-z][a-z0-9_]{1,62}[a-z0-9])?$" + max_bytes: 64 + } + ]; } message ExperimentalUnregisterRelationshipCounterResponse {} @@ -179,26 +274,51 @@ message ExperimentalUnregisterRelationshipCounterResponse {} message BulkCheckPermissionRequest { Consistency consistency = 1; - repeated BulkCheckPermissionRequestItem items = 2 [ (validate.rules).repeated .items.message.required = true, deprecated=true ]; + repeated BulkCheckPermissionRequestItem items = 2 [ + (validate.rules).repeated.items.message.required = true, + (buf.validate.field).repeated.items.required = true, + deprecated = true + ]; } message BulkCheckPermissionRequestItem { - ObjectReference resource = 1 [ (validate.rules).message.required = true ]; - - string permission = 2 [ (validate.rules).string = { - pattern : "^([a-z][a-z0-9_]{1,62}[a-z0-9])?$", - max_bytes : 64, - } ]; + ObjectReference resource = 1 [ + (validate.rules).message.required = true, + (buf.validate.field).required = true + ]; + + string permission = 2 [ + (validate.rules).string = { + pattern: "^([a-z][a-z0-9_]{1,62}[a-z0-9])?$" + max_bytes: 64 + }, + (buf.validate.field).string = { + pattern: "^([a-z][a-z0-9_]{1,62}[a-z0-9])?$" + max_bytes: 64 + } + ]; - SubjectReference subject = 3 [ (validate.rules).message.required = true ]; + SubjectReference subject = 3 [ + (validate.rules).message.required = true, + (buf.validate.field).required = true + ]; - google.protobuf.Struct context = 4 [ (validate.rules).message.required = false ]; + google.protobuf.Struct context = 4 [ + (validate.rules).message.required = false, + (buf.validate.field).required = false + ]; } message BulkCheckPermissionResponse { - ZedToken checked_at = 1 [ (validate.rules).message.required = false ]; + ZedToken checked_at = 1 [ + (validate.rules).message.required = false, + (buf.validate.field).required = false + ]; - repeated BulkCheckPermissionPair pairs = 2 [ (validate.rules).repeated .items.message.required = true ]; + repeated BulkCheckPermissionPair pairs = 2 [ + (validate.rules).repeated.items.message.required = true, + (buf.validate.field).repeated.items.required = true + ]; } message BulkCheckPermissionPair { @@ -210,9 +330,21 @@ message BulkCheckPermissionPair { } message BulkCheckPermissionResponseItem { - CheckPermissionResponse.Permissionship permissionship = 1 [ (validate.rules).enum = {defined_only: true, not_in: [0]} ]; + CheckPermissionResponse.Permissionship permissionship = 1 [ + (validate.rules).enum = { + defined_only: true + not_in: [0] + }, + (buf.validate.field).enum = { + defined_only: true + not_in: [0] + } + ]; - PartialCaveatInfo partial_caveat_info = 2 [ (validate.rules).message.required = false ]; + PartialCaveatInfo partial_caveat_info = 2 [ + (validate.rules).message.required = false, + (buf.validate.field).required = false + ]; } // BulkImportRelationshipsRequest represents one batch of the streaming @@ -223,8 +355,10 @@ message BulkCheckPermissionResponseItem { // invocation are executed under this single transaction. If a relationship already // exists within the datastore, the entire transaction will fail with an error. message BulkImportRelationshipsRequest { - repeated Relationship relationships = 1 - [ (validate.rules).repeated .items.message.required = true ]; + repeated Relationship relationships = 1 [ + (validate.rules).repeated.items.message.required = true, + (buf.validate.field).repeated.items.required = true + ]; } // BulkImportRelationshipsResponse is returned on successful completion of the @@ -242,7 +376,10 @@ message BulkExportRelationshipsRequest { // relationships the server can return in one page. By default, the server // will pick a page size, and the server is free to choose a smaller size // at will. - uint32 optional_limit = 2 [(validate.rules).uint32 = {gte:0}]; + uint32 optional_limit = 2 [ + (validate.rules).uint32 = {gte: 0}, + (buf.validate.field).uint32 = {gte: 0} + ]; // optional_cursor, if specified, indicates the cursor after which results // should resume being returned. The cursor can be found on the @@ -259,7 +396,7 @@ message BulkExportRelationshipsRequest { // server will continue to stream back relationship groups as quickly as it can // until all relationships have been transmitted back. message BulkExportRelationshipsResponse { - Cursor after_result_cursor = 1; + Cursor after_result_cursor = 1; repeated Relationship relationships = 2; } @@ -267,7 +404,7 @@ message BulkExportRelationshipsResponse { message ExperimentalReflectSchemaRequest { Consistency consistency = 1; - + // optional_filters defines optional filters that are applied in // an OR fashion to the schema, before being returned repeated ExpSchemaFilter optional_filters = 2; @@ -306,7 +443,7 @@ message ExpDefinition { // comment is a human-readable comments on the definition. Will include // delimiter characters. string comment = 2; - + repeated ExpRelation relations = 3; repeated ExpPermission permissions = 4; } @@ -352,12 +489,12 @@ message ExpTypeReference { oneof typeref { // is_terminal_subject is true if the subject is terminal, meaning it is referenced directly vs a sub-relation. bool is_terminal_subject = 3; - + // optional_relation_name is the name of the relation that is applied to the subject, if any. string optional_relation_name = 4; // is_public_wildcard is true if the subject is a public wildcard. - bool is_public_wildcard = 5; + bool is_public_wildcard = 5; } } diff --git a/authzed/api/v1/openapi.proto b/authzed/api/v1/openapi.proto index 8fd6632..2e1f000 100644 --- a/authzed/api/v1/openapi.proto +++ b/authzed/api/v1/openapi.proto @@ -1,49 +1,46 @@ syntax = "proto3"; package authzed.api.v1; -option go_package = "github.com/authzed/authzed-go/proto/authzed/api/v1"; -option java_package = "com.authzed.api.v1"; -option java_multiple_files = true; - import "protoc-gen-openapiv2/options/annotations.proto"; +option go_package = "github.com/authzed/authzed-go/proto/authzed/api/v1"; +option java_multiple_files = true; +option java_package = "com.authzed.api.v1"; option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_swagger) = { - info: { - title: "Authzed"; - version: "1.0"; - contact: { - name: "Authzed, Inc."; - url: "https://github.com/authzed/api"; - email: "support@authzed.com"; - }; - license: { - name: "Apache 2.0 License"; - url: "https://github.com/authzed/api/blob/main/LICENSE"; - }; - }; - external_docs: { - url: "https://docs.authzed.com/reference/api"; - description: "More about the Authzed API."; - } - schemes: HTTP; - schemes: HTTPS; - schemes: WSS; - consumes: "application/json"; - produces: "application/json"; - security_definitions: { - security: { - key: "ApiKeyAuth"; - value: { - type: TYPE_API_KEY; - in: IN_HEADER; - name: "Authorization"; - description: "SpiceDB preshared-key, prefixed by Bearer: Bearer "; - } - } - }, - security: { - security_requirement: { - key: "ApiKeyAuth" - } - } + info: { + title: "Authzed" + version: "1.0" + contact: { + name: "Authzed, Inc." + url: "https://github.com/authzed/api" + email: "support@authzed.com" + } + license: { + name: "Apache 2.0 License" + url: "https://github.com/authzed/api/blob/main/LICENSE" + } + } + external_docs: { + url: "https://docs.authzed.com/reference/api" + description: "More about the Authzed API." + } + schemes: HTTP + schemes: HTTPS + schemes: WSS + consumes: "application/json" + produces: "application/json" + security_definitions: { + security: { + key: "ApiKeyAuth" + value: { + type: TYPE_API_KEY + in: IN_HEADER + name: "Authorization" + description: "SpiceDB preshared-key, prefixed by Bearer: Bearer " + } + } + } + security: { + security_requirement: {key: "ApiKeyAuth"} + } }; diff --git a/authzed/api/v1/permission_service.proto b/authzed/api/v1/permission_service.proto index 92be334..ffe66c1 100644 --- a/authzed/api/v1/permission_service.proto +++ b/authzed/api/v1/permission_service.proto @@ -1,105 +1,97 @@ syntax = "proto3"; package authzed.api.v1; -option go_package = "github.com/authzed/authzed-go/proto/authzed/api/v1"; -option java_package = "com.authzed.api.v1"; -option java_multiple_files = true; - -import "google/protobuf/struct.proto"; +import "authzed/api/v1/core.proto"; +import "authzed/api/v1/debug.proto"; +import "buf/validate/validate.proto"; import "google/api/annotations.proto"; +import "google/protobuf/struct.proto"; import "google/rpc/status.proto"; import "google/protobuf/timestamp.proto"; import "validate/validate.proto"; -import "authzed/api/v1/core.proto"; -import "authzed/api/v1/debug.proto"; +option go_package = "github.com/authzed/authzed-go/proto/authzed/api/v1"; +option java_multiple_files = true; +option java_package = "com.authzed.api.v1"; // PermissionsService implements a set of RPCs that perform operations on // relationships and permissions. service PermissionsService { // ReadRelationships reads a set of the relationships matching one or more // filters. - rpc ReadRelationships(ReadRelationshipsRequest) - returns (stream ReadRelationshipsResponse) { - option (google.api.http) = { - post: "/v1/relationships/read" - body: "*" - }; + rpc ReadRelationships(ReadRelationshipsRequest) returns (stream ReadRelationshipsResponse) { + option (google.api.http) = { + post: "/v1/relationships/read" + body: "*" + }; } // WriteRelationships atomically writes and/or deletes a set of specified // relationships. An optional set of preconditions can be provided that must // be satisfied for the operation to commit. - rpc WriteRelationships(WriteRelationshipsRequest) - returns (WriteRelationshipsResponse) { - option (google.api.http) = { - post: "/v1/relationships/write" - body: "*" - }; - } + rpc WriteRelationships(WriteRelationshipsRequest) returns (WriteRelationshipsResponse) { + option (google.api.http) = { + post: "/v1/relationships/write" + body: "*" + }; + } // DeleteRelationships atomically bulk deletes all relationships matching the // provided filter. If no relationships match, none will be deleted and the // operation will succeed. An optional set of preconditions can be provided that must // be satisfied for the operation to commit. - rpc DeleteRelationships(DeleteRelationshipsRequest) - returns (DeleteRelationshipsResponse) { - option (google.api.http) = { - post: "/v1/relationships/delete" - body: "*" - }; - } + rpc DeleteRelationships(DeleteRelationshipsRequest) returns (DeleteRelationshipsResponse) { + option (google.api.http) = { + post: "/v1/relationships/delete" + body: "*" + }; + } // CheckPermission determines for a given resource whether a subject computes // to having a permission or is a direct member of a particular relation. - rpc CheckPermission(CheckPermissionRequest) - returns (CheckPermissionResponse) { - option (google.api.http) = { - post: "/v1/permissions/check" - body: "*" - }; - } + rpc CheckPermission(CheckPermissionRequest) returns (CheckPermissionResponse) { + option (google.api.http) = { + post: "/v1/permissions/check" + body: "*" + }; + } // CheckBulkPermissions evaluates the given list of permission checks // and returns the list of results. - rpc CheckBulkPermissions(CheckBulkPermissionsRequest) - returns (CheckBulkPermissionsResponse) { - option (google.api.http) = { - post: "/v1/permissions/checkbulk" - body: "*" - }; - } + rpc CheckBulkPermissions(CheckBulkPermissionsRequest) returns (CheckBulkPermissionsResponse) { + option (google.api.http) = { + post: "/v1/permissions/checkbulk" + body: "*" + }; + } // ExpandPermissionTree reveals the graph structure for a resource's // permission or relation. This RPC does not recurse infinitely deep and may // require multiple calls to fully unnest a deeply nested graph. - rpc ExpandPermissionTree(ExpandPermissionTreeRequest) - returns (ExpandPermissionTreeResponse) { - option (google.api.http) = { - post: "/v1/permissions/expand" - body: "*" - }; - } + rpc ExpandPermissionTree(ExpandPermissionTreeRequest) returns (ExpandPermissionTreeResponse) { + option (google.api.http) = { + post: "/v1/permissions/expand" + body: "*" + }; + } // LookupResources returns all the resources of a given type that a subject // can access whether via a computed permission or relation membership. - rpc LookupResources(LookupResourcesRequest) - returns (stream LookupResourcesResponse) { - option (google.api.http) = { - post: "/v1/permissions/resources" - body: "*" - }; - } + rpc LookupResources(LookupResourcesRequest) returns (stream LookupResourcesResponse) { + option (google.api.http) = { + post: "/v1/permissions/resources" + body: "*" + }; + } // LookupSubjects returns all the subjects of a given type that // have access whether via a computed permission or relation membership. - rpc LookupSubjects(LookupSubjectsRequest) - returns (stream LookupSubjectsResponse) { - option (google.api.http) = { - post: "/v1/permissions/subjects" - body: "*" - }; - } + rpc LookupSubjects(LookupSubjectsRequest) returns (stream LookupSubjectsResponse) { + option (google.api.http) = { + post: "/v1/permissions/subjects" + body: "*" + }; + } // ImportBulkRelationships is a faster path to writing a large number of // relationships at once. It is both batched and streaming. For maximum @@ -108,24 +100,22 @@ service PermissionsService { // resource.object_id, relation, subject.object.object_type, // subject.object.object_id, subject.optional_relation). All relationships // written are done so under a single transaction. - rpc ImportBulkRelationships(stream ImportBulkRelationshipsRequest) - returns (ImportBulkRelationshipsResponse) { - option (google.api.http) = { - post: "/v1/relationships/importbulk" - body: "*" - }; - } + rpc ImportBulkRelationships(stream ImportBulkRelationshipsRequest) returns (ImportBulkRelationshipsResponse) { + option (google.api.http) = { + post: "/v1/relationships/importbulk" + body: "*" + }; + } // ExportBulkRelationships is the fastest path available to exporting // relationships from the server. It is resumable, and will return results // in an order determined by the server. - rpc ExportBulkRelationships(ExportBulkRelationshipsRequest) - returns (stream ExportBulkRelationshipsResponse) { - option (google.api.http) = { - post: "/v1/relationships/exportbulk" - body: "*" - }; - } + rpc ExportBulkRelationships(ExportBulkRelationshipsRequest) returns (stream ExportBulkRelationshipsResponse) { + option (google.api.http) = { + post: "/v1/relationships/exportbulk" + body: "*" + }; + } } // Consistency will define how a request is handled by the backend. @@ -134,10 +124,14 @@ service PermissionsService { message Consistency { oneof requirement { option (validate.required) = true; + option (buf.validate.oneof).required = true; // minimize_latency indicates that the latency for the call should be // minimized by having the system select the fastest snapshot available. - bool minimize_latency = 1 [ (validate.rules).bool.const = true ]; + bool minimize_latency = 1 [ + (validate.rules).bool.const = true, + (buf.validate.field).bool.const = true + ]; // at_least_as_fresh indicates that all data used in the API call must be // *at least as fresh* as that found in the ZedToken; more recent data might @@ -155,7 +149,10 @@ message Consistency { // NOTE: using this method can be *quite slow*, so unless there is a need to // do so, it is recommended to use `at_least_as_fresh` with a stored // ZedToken. - bool fully_consistent = 4 [ (validate.rules).bool.const = true ]; + bool fully_consistent = 4 [ + (validate.rules).bool.const = true, + (buf.validate.field).bool.const = true + ]; } } @@ -171,31 +168,54 @@ message Consistency { message RelationshipFilter { // resource_type is the *optional* resource type of the relationship. // NOTE: It is not prefixed with "optional_" for legacy compatibility. - string resource_type = 1 [ (validate.rules).string = { - pattern : "^(([a-z][a-z0-9_]{1,61}[a-z0-9]/)*[a-z][a-z0-9_]{1,62}[a-z0-9])?$", - max_bytes : 128, - } ]; + string resource_type = 1 [ + (validate.rules).string = { + pattern: "^(([a-z][a-z0-9_]{1,61}[a-z0-9]/)*[a-z][a-z0-9_]{1,62}[a-z0-9])?$" + max_bytes: 128 + }, + (buf.validate.field).string = { + pattern: "^(([a-z][a-z0-9_]{1,61}[a-z0-9]/)*[a-z][a-z0-9_]{1,62}[a-z0-9])?$" + max_bytes: 128 + } + ]; // optional_resource_id is the *optional* resource ID of the relationship. // If specified, optional_resource_id_prefix cannot be specified. - string optional_resource_id = 2 [ (validate.rules).string = { - pattern : "^([a-zA-Z0-9/_|\\-=+]{1,})?$", - max_bytes : 1024, - } ]; + string optional_resource_id = 2 [ + (validate.rules).string = { + pattern: "^([a-zA-Z0-9/_|\\-=+]{1,})?$" + max_bytes: 1024 + }, + (buf.validate.field).string = { + pattern: "^([a-zA-Z0-9/_|\\-=+]{1,})?$" + max_bytes: 1024 + } + ]; // optional_resource_id_prefix is the *optional* prefix for the resource ID of the relationship. // If specified, optional_resource_id cannot be specified. - string optional_resource_id_prefix = 5 [ (validate.rules).string = { - pattern : "^([a-zA-Z0-9/_|\\-=+]{1,})?$", - max_bytes : 1024, - } ]; - + string optional_resource_id_prefix = 5 [ + (validate.rules).string = { + pattern: "^([a-zA-Z0-9/_|\\-=+]{1,})?$" + max_bytes: 1024 + }, + (buf.validate.field).string = { + pattern: "^([a-zA-Z0-9/_|\\-=+]{1,})?$" + max_bytes: 1024 + } + ]; // relation is the *optional* relation of the relationship. - string optional_relation = 3 [ (validate.rules).string = { - pattern : "^([a-z][a-z0-9_]{1,62}[a-z0-9])?$", - max_bytes : 64, - } ]; + string optional_relation = 3 [ + (validate.rules).string = { + pattern: "^([a-z][a-z0-9_]{1,62}[a-z0-9])?$" + max_bytes: 64 + }, + (buf.validate.field).string = { + pattern: "^([a-z][a-z0-9_]{1,62}[a-z0-9])?$" + max_bytes: 64 + } + ]; // optional_subject_filter is the optional filter for the subjects of the relationships. SubjectFilter optional_subject_filter = 4; @@ -207,21 +227,39 @@ message RelationshipFilter { // impose any additional requirements if left unspecified. message SubjectFilter { message RelationFilter { - string relation = 1 [ (validate.rules).string = { - pattern : "^([a-z][a-z0-9_]{1,62}[a-z0-9])?$", - max_bytes : 64, - } ]; + string relation = 1 [ + (validate.rules).string = { + pattern: "^([a-z][a-z0-9_]{1,62}[a-z0-9])?$" + max_bytes: 64 + }, + (buf.validate.field).string = { + pattern: "^([a-z][a-z0-9_]{1,62}[a-z0-9])?$" + max_bytes: 64 + } + ]; } - string subject_type = 1 [ (validate.rules).string = { - pattern : "^([a-z][a-z0-9_]{1,61}[a-z0-9]/)*[a-z][a-z0-9_]{1,62}[a-z0-9]$", - max_bytes : 128, - } ]; - - string optional_subject_id = 2 [ (validate.rules).string = { - pattern : "^(([a-zA-Z0-9/_|\\-=+]{1,})|\\*)?$", - max_bytes : 1024, - } ]; + string subject_type = 1 [ + (validate.rules).string = { + pattern: "^([a-z][a-z0-9_]{1,61}[a-z0-9]/)*[a-z][a-z0-9_]{1,62}[a-z0-9]$" + max_bytes: 128 + }, + (buf.validate.field).string = { + pattern: "^([a-z][a-z0-9_]{1,61}[a-z0-9]/)*[a-z][a-z0-9_]{1,62}[a-z0-9]$" + max_bytes: 128 + } + ]; + + string optional_subject_id = 2 [ + (validate.rules).string = { + pattern: "^(([a-zA-Z0-9/_|\\-=+]{1,})|\\*)?$" + max_bytes: 1024 + }, + (buf.validate.field).string = { + pattern: "^(([a-zA-Z0-9/_|\\-=+]{1,})|\\*)?$" + max_bytes: 1024 + } + ]; RelationFilter optional_relation = 3; } @@ -233,14 +271,19 @@ message ReadRelationshipsRequest { // relationship_filter defines the filter to be applied to the relationships // to be returned. - RelationshipFilter relationship_filter = 2 - [ (validate.rules).message.required = true ]; + RelationshipFilter relationship_filter = 2 [ + (validate.rules).message.required = true, + (buf.validate.field).required = true + ]; // optional_limit, if non-zero, specifies the limit on the number of relationships to return // before the stream is closed on the server side. By default, the stream will continue // resolving relationships until exhausted or the stream is closed due to the client or a // network issue. - uint32 optional_limit = 3 [(validate.rules).uint32 = {gte:0}]; + uint32 optional_limit = 3 [ + (validate.rules).uint32 = {gte: 0}, + (buf.validate.field).uint32 = {gte: 0} + ]; // optional_cursor, if specified, indicates the cursor after which results should resume being returned. // The cursor can be found on the ReadRelationshipsResponse object. @@ -252,10 +295,16 @@ message ReadRelationshipsRequest { // be streamed to the client for each relationship found. message ReadRelationshipsResponse { // read_at is the ZedToken at which the relationship was found. - ZedToken read_at = 1 [ (validate.rules).message.required = true ]; + ZedToken read_at = 1 [ + (validate.rules).message.required = true, + (buf.validate.field).required = true + ]; // relationship is the found relationship. - Relationship relationship = 2 [ (validate.rules).message.required = true ]; + Relationship relationship = 2 [ + (validate.rules).message.required = true, + (buf.validate.field).required = true + ]; // after_result_cursor holds a cursor that can be used to resume the ReadRelationships stream after this // result. @@ -277,8 +326,20 @@ message Precondition { OPERATION_MUST_MATCH = 2; } - Operation operation = 1 [ (validate.rules).enum = {defined_only: true, not_in: [0]} ]; - RelationshipFilter filter = 2 [ (validate.rules).message.required = true ]; + Operation operation = 1 [ + (validate.rules).enum = { + defined_only: true + not_in: [0] + }, + (buf.validate.field).enum = { + defined_only: true + not_in: [0] + } + ]; + RelationshipFilter filter = 2 [ + (validate.rules).message.required = true, + (buf.validate.field).required = true + ]; } // WriteRelationshipsRequest contains a list of Relationship mutations that @@ -287,20 +348,28 @@ message Precondition { // the write will be committed. All updates will be applied transactionally, // and if any preconditions fail, the entire transaction will be reverted. message WriteRelationshipsRequest { - repeated RelationshipUpdate updates = 1 - [ (validate.rules).repeated .items.message.required = true ]; + repeated RelationshipUpdate updates = 1 [ + (validate.rules).repeated.items.message.required = true, + (buf.validate.field).repeated.items.required = true + ]; - repeated Precondition optional_preconditions = 2 - [ (validate.rules).repeated .items.message.required = - true ]; // To be bounded by configuration + repeated Precondition optional_preconditions = 2 [ + (validate.rules).repeated.items.message.required = true, + (buf.validate.field).repeated.items.required = true + ]; // To be bounded by configuration // optional_transaction_metadata is an optional field that can be used to store metadata about the transaction. // If specified, this metadata will be supplied in the WatchResponse for the updates associated with this // transaction. - google.protobuf.Struct optional_transaction_metadata = 3 [ (validate.rules).message.required = false ]; + google.protobuf.Struct optional_transaction_metadata = 3 [ + (validate.rules).message.required = false, + (buf.validate.field).required = false + ]; } -message WriteRelationshipsResponse { ZedToken written_at = 1; } +message WriteRelationshipsResponse { + ZedToken written_at = 1; +} // DeleteRelationshipsRequest specifies which Relationships should be deleted, // requesting the delete of *ALL* relationships that match the specified @@ -308,19 +377,25 @@ message WriteRelationshipsResponse { ZedToken written_at = 1; } // specified preconditions must also be satisfied before the delete will be // executed. message DeleteRelationshipsRequest { - RelationshipFilter relationship_filter = 1 - [ (validate.rules).message.required = true ]; + RelationshipFilter relationship_filter = 1 [ + (validate.rules).message.required = true, + (buf.validate.field).required = true + ]; - repeated Precondition optional_preconditions = 2 - [ (validate.rules).repeated .items.message.required = - true ]; // To be bounded by configuration + repeated Precondition optional_preconditions = 2 [ + (validate.rules).repeated.items.message.required = true, + (buf.validate.field).repeated.items.required = true + ]; // To be bounded by configuration // optional_limit, if non-zero, specifies the limit on the number of relationships to be deleted. // If there are more matching relationships found to be deleted than the limit specified here, // the deletion call will fail with an error to prevent partial deletion. If partial deletion // is needed, specify below that partial deletion is allowed. Partial deletions can be used // in a loop to delete large amounts of relationships in a *non-transactional* manner. - uint32 optional_limit = 3 [(validate.rules).uint32 = {gte:0}]; + uint32 optional_limit = 3 [ + (validate.rules).uint32 = {gte: 0}, + (buf.validate.field).uint32 = {gte: 0} + ]; // optional_allow_partial_deletions, if true and a limit is specified, will delete matching found // relationships up to the count specified in optional_limit, and no more. @@ -329,13 +404,16 @@ message DeleteRelationshipsRequest { // optional_transaction_metadata is an optional field that can be used to store metadata about the transaction. // If specified, this metadata will be supplied in the WatchResponse for the deletions associated with // this transaction. - google.protobuf.Struct optional_transaction_metadata = 5 [ (validate.rules).message.required = false ]; + google.protobuf.Struct optional_transaction_metadata = 5 [ + (validate.rules).message.required = false, + (buf.validate.field).required = false + ]; } message DeleteRelationshipsResponse { enum DeletionProgress { DELETION_PROGRESS_UNSPECIFIED = 0; - + // DELETION_PROGRESS_COMPLETE indicates that all remaining relationships matching the filter // were deleted. Will be returned even if no relationships were deleted. DELETION_PROGRESS_COMPLETE = 1; @@ -363,20 +441,35 @@ message CheckPermissionRequest { Consistency consistency = 1; // resource is the resource on which to check the permission or relation. - ObjectReference resource = 2 [ (validate.rules).message.required = true ]; + ObjectReference resource = 2 [ + (validate.rules).message.required = true, + (buf.validate.field).required = true + ]; // permission is the name of the permission (or relation) on which to execute // the check. - string permission = 3 [ (validate.rules).string = { - pattern : "^([a-z][a-z0-9_]{1,62}[a-z0-9])?$", - max_bytes : 64, - } ]; + string permission = 3 [ + (validate.rules).string = { + pattern: "^([a-z][a-z0-9_]{1,62}[a-z0-9])?$" + max_bytes: 64 + }, + (buf.validate.field).string = { + pattern: "^([a-z][a-z0-9_]{1,62}[a-z0-9])?$" + max_bytes: 64 + } + ]; // subject is the subject that will be checked for the permission or relation. - SubjectReference subject = 4 [ (validate.rules).message.required = true ]; + SubjectReference subject = 4 [ + (validate.rules).message.required = true, + (buf.validate.field).required = true + ]; // context consists of named values that are injected into the caveat evaluation context - google.protobuf.Struct context = 5 [ (validate.rules).message.required = false ]; + google.protobuf.Struct context = 5 [ + (validate.rules).message.required = false, + (buf.validate.field).required = false + ]; // with_tracing, if true, indicates that the response should include a debug trace. // This can be useful for debugging and performance analysis, but adds a small amount @@ -392,7 +485,10 @@ message CheckPermissionResponse { PERMISSIONSHIP_CONDITIONAL_PERMISSION = 3; } - ZedToken checked_at = 1 [ (validate.rules).message.required = false ]; + ZedToken checked_at = 1 [ + (validate.rules).message.required = false, + (buf.validate.field).required = false + ]; // Permissionship communicates whether or not the subject has the requested // permission or has a relationship with the given resource, over the given @@ -402,10 +498,22 @@ message CheckPermissionResponse { // requested subject is a member of the computed permission set or there // exists a relationship with the requested relation from the given resource // to the given subject. - Permissionship permissionship = 2 [ (validate.rules).enum = {defined_only: true, not_in: [0]} ]; + Permissionship permissionship = 2 [ + (validate.rules).enum = { + defined_only: true + not_in: [0] + }, + (buf.validate.field).enum = { + defined_only: true + not_in: [0] + } + ]; // partial_caveat_info holds information of a partially-evaluated caveated response - PartialCaveatInfo partial_caveat_info = 3 [ (validate.rules).message.required = false ]; + PartialCaveatInfo partial_caveat_info = 3 [ + (validate.rules).message.required = false, + (buf.validate.field).required = false + ]; // debug_trace is the debugging trace of this check, if requested. DebugInformation debug_trace = 4; @@ -415,7 +523,7 @@ message CheckPermissionResponse { google.protobuf.Timestamp optional_expires_at = 5; } -// CheckBulkPermissionsRequest issues a check on whether a subject has permission +// CheckBulkPermissionsRequest issues a check on whether a subject has permission // or is a member of a relation on a specific resource for each item in the list. // // The ordering of the items in the response is maintained in the response. @@ -423,31 +531,56 @@ message CheckPermissionResponse { message CheckBulkPermissionsRequest { Consistency consistency = 1; - repeated CheckBulkPermissionsRequestItem items = 2 [ (validate.rules).repeated .items.message.required = true ]; // with_tracing, if true, indicates that each response should include a debug trace. // This can be useful for debugging and performance analysis, but adds a small amount // of compute overhead to the request. bool with_tracing = 3; + repeated CheckBulkPermissionsRequestItem items = 2 [(validate.rules).repeated.items.message.required = true]; + repeated CheckBulkPermissionsRequestItem items = 2 [ + (validate.rules).repeated.items.message.required = true, + (buf.validate.field).repeated.items.required = true + ]; } message CheckBulkPermissionsRequestItem { - ObjectReference resource = 1 [ (validate.rules).message.required = true ]; - - string permission = 2 [ (validate.rules).string = { - pattern : "^([a-z][a-z0-9_]{1,62}[a-z0-9])?$", - max_bytes : 64, - } ]; + ObjectReference resource = 1 [ + (validate.rules).message.required = true, + (buf.validate.field).required = true + ]; + + string permission = 2 [ + (validate.rules).string = { + pattern: "^([a-z][a-z0-9_]{1,62}[a-z0-9])?$" + max_bytes: 64 + }, + (buf.validate.field).string = { + pattern: "^([a-z][a-z0-9_]{1,62}[a-z0-9])?$" + max_bytes: 64 + } + ]; - SubjectReference subject = 3 [ (validate.rules).message.required = true ]; + SubjectReference subject = 3 [ + (validate.rules).message.required = true, + (buf.validate.field).required = true + ]; - google.protobuf.Struct context = 4 [ (validate.rules).message.required = false ]; + google.protobuf.Struct context = 4 [ + (validate.rules).message.required = false, + (buf.validate.field).required = false + ]; } message CheckBulkPermissionsResponse { - ZedToken checked_at = 1 [ (validate.rules).message.required = false ]; - - repeated CheckBulkPermissionsPair pairs = 2 [ (validate.rules).repeated .items.message.required = true ]; + ZedToken checked_at = 1 [ + (validate.rules).message.required = false, + (buf.validate.field).required = false + ]; + + repeated CheckBulkPermissionsPair pairs = 2 [ + (validate.rules).repeated.items.message.required = true, + (buf.validate.field).repeated.items.required = true + ]; } message CheckBulkPermissionsPair { @@ -459,12 +592,25 @@ message CheckBulkPermissionsPair { } message CheckBulkPermissionsResponseItem { - CheckPermissionResponse.Permissionship permissionship = 1 [ (validate.rules).enum = {defined_only: true, not_in: [0]} ]; + CheckPermissionResponse.Permissionship permissionship = 1 [ + (validate.rules).enum = { + defined_only: true + not_in: [0] + }, + (buf.validate.field).enum = { + defined_only: true + not_in: [0] + } + ]; - PartialCaveatInfo partial_caveat_info = 2 [ (validate.rules).message.required = false ]; // debug_trace is the debugging trace of this check, if requested. DebugInformation debug_trace = 3; + PartialCaveatInfo partial_caveat_info = 2 [(validate.rules).message.required = false]; + PartialCaveatInfo partial_caveat_info = 2 [ + (validate.rules).message.required = false, + (buf.validate.field).required = false + ]; } // ExpandPermissionTreeRequest returns a tree representing the expansion of all @@ -478,14 +624,23 @@ message ExpandPermissionTreeRequest { Consistency consistency = 1; // resource is the resource over which to run the expansion. - ObjectReference resource = 2 [ (validate.rules).message.required = true ]; + ObjectReference resource = 2 [ + (validate.rules).message.required = true, + (buf.validate.field).required = true + ]; // permission is the name of the permission or relation over which to run the // expansion for the resource. - string permission = 3 [ (validate.rules).string = { - pattern : "^([a-z][a-z0-9_]{1,62}[a-z0-9])?$", - max_bytes : 64, - } ]; + string permission = 3 [ + (validate.rules).string = { + pattern: "^([a-z][a-z0-9_]{1,62}[a-z0-9])?$" + max_bytes: 64 + }, + (buf.validate.field).string = { + pattern: "^([a-z][a-z0-9_]{1,62}[a-z0-9])?$" + max_bytes: 64 + } + ]; } message ExpandPermissionTreeResponse { @@ -505,29 +660,50 @@ message LookupResourcesRequest { // resource_object_type is the type of resource object for which the IDs will // be returned. - string resource_object_type = 2 [ (validate.rules).string = { - pattern : "^([a-z][a-z0-9_]{1,61}[a-z0-9]/)*[a-z][a-z0-9_]{1,62}[a-z0-9]$", - max_bytes : 128, - } ]; + string resource_object_type = 2 [ + (validate.rules).string = { + pattern: "^([a-z][a-z0-9_]{1,61}[a-z0-9]/)*[a-z][a-z0-9_]{1,62}[a-z0-9]$" + max_bytes: 128 + }, + (buf.validate.field).string = { + pattern: "^([a-z][a-z0-9_]{1,61}[a-z0-9]/)*[a-z][a-z0-9_]{1,62}[a-z0-9]$" + max_bytes: 128 + } + ]; // permission is the name of the permission or relation for which the subject // must Check. - string permission = 3 [ (validate.rules).string = { - pattern : "^[a-z][a-z0-9_]{1,62}[a-z0-9]$", - max_bytes : 64, - } ]; + string permission = 3 [ + (validate.rules).string = { + pattern: "^[a-z][a-z0-9_]{1,62}[a-z0-9]$" + max_bytes: 64 + }, + (buf.validate.field).string = { + pattern: "^[a-z][a-z0-9_]{1,62}[a-z0-9]$" + max_bytes: 64 + } + ]; // subject is the subject with access to the resources. - SubjectReference subject = 4 [ (validate.rules).message.required = true ]; + SubjectReference subject = 4 [ + (validate.rules).message.required = true, + (buf.validate.field).required = true + ]; // context consists of named values that are injected into the caveat evaluation context - google.protobuf.Struct context = 5 [ (validate.rules).message.required = false ]; + google.protobuf.Struct context = 5 [ + (validate.rules).message.required = false, + (buf.validate.field).required = false + ]; // optional_limit, if non-zero, specifies the limit on the number of resources to return // before the stream is closed on the server side. By default, the stream will continue // resolving resources until exhausted or the stream is closed due to the client or a // network issue. - uint32 optional_limit = 6 [(validate.rules).uint32 = {gte:0}]; + uint32 optional_limit = 6 [ + (validate.rules).uint32 = {gte: 0}, + (buf.validate.field).uint32 = {gte: 0} + ]; // optional_cursor, if specified, indicates the cursor after which results should resume being returned. // The cursor can be found on the LookupResourcesResponse object. @@ -551,10 +727,22 @@ message LookupResourcesResponse { string resource_object_id = 2; // permissionship indicates whether the response was partially evaluated or not - LookupPermissionship permissionship = 3 [ (validate.rules).enum = {defined_only: true, not_in: [0]} ]; + LookupPermissionship permissionship = 3 [ + (validate.rules).enum = { + defined_only: true + not_in: [0] + }, + (buf.validate.field).enum = { + defined_only: true + not_in: [0] + } + ]; // partial_caveat_info holds information of a partially-evaluated caveated response - PartialCaveatInfo partial_caveat_info = 4 [ (validate.rules).message.required = false ]; + PartialCaveatInfo partial_caveat_info = 4 [ + (validate.rules).message.required = false, + (buf.validate.field).required = false + ]; // after_result_cursor holds a cursor that can be used to resume the LookupResources stream after this // result. @@ -575,30 +763,54 @@ message LookupSubjectsRequest { // resource is the resource for which all matching subjects for the permission // or relation will be returned. - ObjectReference resource = 2 [ (validate.rules).message.required = true ]; + ObjectReference resource = 2 [ + (validate.rules).message.required = true, + (buf.validate.field).required = true + ]; // permission is the name of the permission (or relation) for which to find // the subjects. - string permission = 3 [ (validate.rules).string = { - pattern : "^([a-z][a-z0-9_]{1,62}[a-z0-9])?$", - max_bytes : 64, - } ]; + string permission = 3 [ + (validate.rules).string = { + pattern: "^([a-z][a-z0-9_]{1,62}[a-z0-9])?$" + max_bytes: 64 + }, + (buf.validate.field).string = { + pattern: "^([a-z][a-z0-9_]{1,62}[a-z0-9])?$" + max_bytes: 64 + } + ]; // subject_object_type is the type of subject object for which the IDs will // be returned. - string subject_object_type = 4 [ (validate.rules).string = { - pattern : "^([a-z][a-z0-9_]{1,61}[a-z0-9]/)*[a-z][a-z0-9_]{1,62}[a-z0-9]$", - max_bytes : 128, - } ]; + string subject_object_type = 4 [ + (validate.rules).string = { + pattern: "^([a-z][a-z0-9_]{1,61}[a-z0-9]/)*[a-z][a-z0-9_]{1,62}[a-z0-9]$" + max_bytes: 128 + }, + (buf.validate.field).string = { + pattern: "^([a-z][a-z0-9_]{1,61}[a-z0-9]/)*[a-z][a-z0-9_]{1,62}[a-z0-9]$" + max_bytes: 128 + } + ]; // optional_subject_relation is the optional relation for the subject. - string optional_subject_relation = 5 [ (validate.rules).string = { - pattern : "^([a-z][a-z0-9_]{1,62}[a-z0-9])?$", - max_bytes : 64, - } ]; + string optional_subject_relation = 5 [ + (validate.rules).string = { + pattern: "^([a-z][a-z0-9_]{1,62}[a-z0-9])?$" + max_bytes: 64 + }, + (buf.validate.field).string = { + pattern: "^([a-z][a-z0-9_]{1,62}[a-z0-9])?$" + max_bytes: 64 + } + ]; // context consists of named values that are injected into the caveat evaluation context - google.protobuf.Struct context = 6 [ (validate.rules).message.required = false ]; + google.protobuf.Struct context = 6 [ + (validate.rules).message.required = false, + (buf.validate.field).required = false + ]; // optional_concrete_limit, if non-zero, specifies the limit on the number of // *concrete* (non-wildcard) subjects to return before the stream is closed on the @@ -620,7 +832,10 @@ message LookupSubjectsRequest { // for each invocation of the API. // // ***IT IS UP TO THE CALLER IN THIS CASE TO COMBINE THE EXCLUSIONS IF DESIRED*** - uint32 optional_concrete_limit = 7 [(validate.rules).uint32 = {gte:0}]; + uint32 optional_concrete_limit = 7 [ + (validate.rules).uint32 = {gte: 0}, + (buf.validate.field).uint32 = {gte: 0} + ]; // optional_cursor, if specified, indicates the cursor after which results should resume being returned. // The cursor can be found on the LookupSubjectsResponse object. @@ -651,11 +866,25 @@ message LookupSubjectsResponse { // permissionship indicates whether the response was partially evaluated or not // deprecated: use `subject.permissionship` - LookupPermissionship permissionship = 4 [ deprecated = true, (validate.rules).enum = {defined_only: true, not_in: [0]} ]; + LookupPermissionship permissionship = 4 [ + deprecated = true, + (validate.rules).enum = { + defined_only: true + not_in: [0] + }, + (buf.validate.field).enum = { + defined_only: true + not_in: [0] + } + ]; // partial_caveat_info holds information of a partially-evaluated caveated response // deprecated: use `subject.partial_caveat_info` - PartialCaveatInfo partial_caveat_info = 5 [ deprecated = true, (validate.rules).message.required = false ]; + PartialCaveatInfo partial_caveat_info = 5 [ + deprecated = true, + (validate.rules).message.required = false, + (buf.validate.field).required = false + ]; // subject is the subject found, along with its permissionship. ResolvedSubject subject = 6; @@ -677,10 +906,22 @@ message ResolvedSubject { string subject_object_id = 1; // permissionship indicates whether the response was partially evaluated or not - LookupPermissionship permissionship = 2 [ (validate.rules).enum = {defined_only: true, not_in: [0]} ]; + LookupPermissionship permissionship = 2 [ + (validate.rules).enum = { + defined_only: true + not_in: [0] + }, + (buf.validate.field).enum = { + defined_only: true + not_in: [0] + } + ]; // partial_caveat_info holds information of a partially-evaluated caveated response - PartialCaveatInfo partial_caveat_info = 3 [ (validate.rules).message.required = false ]; + PartialCaveatInfo partial_caveat_info = 3 [ + (validate.rules).message.required = false, + (buf.validate.field).required = false + ]; } // ImportBulkRelationshipsRequest represents one batch of the streaming @@ -691,8 +932,10 @@ message ResolvedSubject { // invocation are executed under this single transaction. If a relationship already // exists within the datastore, the entire transaction will fail with an error. message ImportBulkRelationshipsRequest { - repeated Relationship relationships = 1 - [ (validate.rules).repeated .items.message.required = true ]; + repeated Relationship relationships = 1 [ + (validate.rules).repeated.items.message.required = true, + (buf.validate.field).repeated.items.required = true + ]; } // ImportBulkRelationshipsResponse is returned on successful completion of the @@ -710,7 +953,10 @@ message ExportBulkRelationshipsRequest { // relationships the server can return in one page. By default, the server // will pick a page size, and the server is free to choose a smaller size // at will. - uint32 optional_limit = 2 [(validate.rules).uint32 = {gte:0}]; + uint32 optional_limit = 2 [ + (validate.rules).uint32 = {gte: 0}, + (buf.validate.field).uint32 = {gte: 0} + ]; // optional_cursor, if specified, indicates the cursor after which results // should resume being returned. The cursor can be found on the @@ -727,6 +973,6 @@ message ExportBulkRelationshipsRequest { // server will continue to stream back relationship groups as quickly as it can // until all relationships have been transmitted back. message ExportBulkRelationshipsResponse { - Cursor after_result_cursor = 1; + Cursor after_result_cursor = 1; repeated Relationship relationships = 2; } diff --git a/authzed/api/v1/schema_service.proto b/authzed/api/v1/schema_service.proto index 263f0f5..8908ce9 100644 --- a/authzed/api/v1/schema_service.proto +++ b/authzed/api/v1/schema_service.proto @@ -1,7 +1,13 @@ syntax = "proto3"; package authzed.api.v1; +import "authzed/api/v1/core.proto"; +import "buf/validate/validate.proto"; +import "google/api/annotations.proto"; +import "validate/validate.proto"; + option go_package = "github.com/authzed/authzed-go/proto/authzed/api/v1"; +option java_multiple_files = true; option java_package = "com.authzed.api.v1"; option java_multiple_files = true; @@ -10,6 +16,12 @@ import "validate/validate.proto"; import "authzed/api/v1/core.proto"; import "authzed/api/v1/permission_service.proto"; +option java_multiple_files = true; + +import "google/api/annotations.proto"; +import "validate/validate.proto"; + +import "authzed/api/v1/core.proto"; // SchemaService implements operations on a Permissions System's Schema. service SchemaService { @@ -87,7 +99,10 @@ message ReadSchemaResponse { string schema_text = 1; // read_at is the ZedToken at which the schema was read. - ZedToken read_at = 2 [ (validate.rules).message.required = true ]; + ZedToken read_at = 2 [ + (validate.rules).message.required = true, + (buf.validate.field).required = true + ]; } // WriteSchemaRequest is the required data used to "upsert" the Schema of a @@ -95,14 +110,20 @@ message ReadSchemaResponse { message WriteSchemaRequest { // The Schema containing one or more Object Definitions that will be written // to the Permissions System. - string schema = 1 [ (validate.rules).string.max_bytes = 4194304 ]; // 4MiB + string schema = 1 [ + (validate.rules).string.max_bytes = 4194304, + (buf.validate.field).string.max_bytes = 4194304 + ]; // 4MiB } // WriteSchemaResponse is the resulting data after having written a Schema to // a Permissions System. message WriteSchemaResponse { - // written_at is the ZedToken at which the schema was written. - ZedToken written_at = 1 [ (validate.rules).message.required = true ]; + // written_at is the ZedToken at which the schema was written. + ZedToken written_at = 1 [ + (validate.rules).message.required = true, + (buf.validate.field).required = true + ]; } // Reflection types //////////////////////////////////////////// diff --git a/authzed/api/v1/watch_service.proto b/authzed/api/v1/watch_service.proto index cc3b24d..79706f9 100644 --- a/authzed/api/v1/watch_service.proto +++ b/authzed/api/v1/watch_service.proto @@ -1,16 +1,16 @@ syntax = "proto3"; package authzed.api.v1; -option go_package = "github.com/authzed/authzed-go/proto/authzed/api/v1"; -option java_package = "com.authzed.api.v1"; -option java_multiple_files = true; - +import "authzed/api/v1/core.proto"; +import "authzed/api/v1/permission_service.proto"; +import "buf/validate/validate.proto"; import "google/api/annotations.proto"; import "google/protobuf/struct.proto"; import "validate/validate.proto"; -import "authzed/api/v1/core.proto"; -import "authzed/api/v1/permission_service.proto"; +option go_package = "github.com/authzed/authzed-go/proto/authzed/api/v1"; +option java_multiple_files = true; +option java_package = "com.authzed.api.v1"; service WatchService { rpc Watch(WatchRequest) returns (stream WatchResponse) { @@ -29,11 +29,19 @@ message WatchRequest { // If specified, only changes to the specified object types will be returned and // optional_relationship_filters cannot be used. repeated string optional_object_types = 1 [ - (validate.rules).repeated .min_items = 0, - (validate.rules).repeated .items.string = { - pattern : "^([a-z][a-z0-9_]{1,62}[a-z0-9]/" - ")*[a-z][a-z0-9_]{1,62}[a-z0-9]$", - max_bytes : 128, + (validate.rules).repeated.min_items = 0, + (buf.validate.field).repeated.min_items = 0, + (validate.rules).repeated.items.string = { + pattern: + "^([a-z][a-z0-9_]{1,62}[a-z0-9]/" + ")*[a-z][a-z0-9_]{1,62}[a-z0-9]$" + max_bytes: 128 + }, + (buf.validate.field).repeated.items.string = { + pattern: + "^([a-z][a-z0-9_]{1,62}[a-z0-9]/" + ")*[a-z][a-z0-9_]{1,62}[a-z0-9]$" + max_bytes: 128 } ]; diff --git a/authzed/api/v1alpha1/schema.proto b/authzed/api/v1alpha1/schema.proto index 9cde043..27b564a 100644 --- a/authzed/api/v1alpha1/schema.proto +++ b/authzed/api/v1alpha1/schema.proto @@ -1,11 +1,12 @@ syntax = "proto3"; package authzed.api.v1alpha1; +import "buf/validate/validate.proto"; +import "validate/validate.proto"; + option go_package = "github.com/authzed/authzed-go/proto/authzed/api/v1alpha1"; option java_package = "com.authzed.api.v1alpha1"; -import "validate/validate.proto"; - // SchemaService implements operations on a Permissions System's Schema. service SchemaService { // Read returns the current Object Definitions for a Permissions System. @@ -13,7 +14,7 @@ service SchemaService { // Errors include: // - INVALID_ARGUMENT: a provided value has failed to semantically validate // - NOT_FOUND: one of the Object Definitions being requested does not exist - rpc ReadSchema(ReadSchemaRequest) returns (ReadSchemaResponse) {} + rpc ReadSchema(ReadSchemaRequest) returns (ReadSchemaResponse) {} // Write overwrites the current Object Definitions for a Permissions System. // @@ -23,15 +24,21 @@ service SchemaService { // ReadSchemaRequest is the required data to read Object Definitions from // a Schema. -message ReadSchemaRequest { +message ReadSchemaRequest { // The list of names of the Object Definitions that are being requested. // // These names must be fully qualified with their namespace (e.g. // myblog/post). - repeated string object_definitions_names = 1 [ (validate.rules).repeated .items.string = { - pattern: "^([a-z][a-z0-9_]{1,62}[a-z0-9]/)*[a-z][a-z0-9_]{1,62}[a-z0-9]$", - max_bytes: 128, - } ]; + repeated string object_definitions_names = 1 [ + (validate.rules).repeated.items.string = { + pattern: "^([a-z][a-z0-9_]{1,62}[a-z0-9]/)*[a-z][a-z0-9_]{1,62}[a-z0-9]$" + max_bytes: 128 + }, + (buf.validate.field).repeated.items.string = { + pattern: "^([a-z][a-z0-9_]{1,62}[a-z0-9]/)*[a-z][a-z0-9_]{1,62}[a-z0-9]$" + max_bytes: 128 + } + ]; } // ReadSchemaResponse is the resulting data after having read the Object @@ -49,7 +56,10 @@ message ReadSchemaResponse { message WriteSchemaRequest { // The Schema containing one or more Object Definitions that will be written // to the Permissions System. - string schema = 1 [ (validate.rules).string.max_bytes = 262144 ]; // 256KiB + string schema = 1 [ + (validate.rules).string.max_bytes = 262144, + (buf.validate.field).string.max_bytes = 262144 + ]; // 256KiB // If specified, the existing revision of object definitions in the schema that must be present for // the write to succeed. If the revision specified differs (i.e. the underlying schema has changed), diff --git a/authzed/api/v1alpha1/watchresources_service.proto b/authzed/api/v1alpha1/watchresources_service.proto index 7405121..fe610fa 100644 --- a/authzed/api/v1alpha1/watchresources_service.proto +++ b/authzed/api/v1alpha1/watchresources_service.proto @@ -1,46 +1,55 @@ syntax = "proto3"; package authzed.api.v1alpha1; -option go_package = "github.com/authzed/authzed-go/proto/authzed/api/v1alpha1"; -option java_package = "com.authzed.api.v1alpha1"; - +import "authzed/api/v1/core.proto"; +import "buf/validate/validate.proto"; import "google/api/annotations.proto"; import "validate/validate.proto"; -import "authzed/api/v1/core.proto"; +option go_package = "github.com/authzed/authzed-go/proto/authzed/api/v1alpha1"; +option java_package = "com.authzed.api.v1alpha1"; // WatchResourcesService is used to receive a stream of updates for resources of a // specific (resource type, permission, subject) combination. service WatchResourcesService { - // WatchResources initiates a watch for permission changes for the provided // (resource type, permission, subject) pair. - rpc WatchResources(WatchResourcesRequest) - returns (stream WatchResourcesResponse) { - option (google.api.http) = { - post: "/v1alpha1/lookupwatch" - body: "*" - }; - } + rpc WatchResources(WatchResourcesRequest) returns (stream WatchResourcesResponse) { + option (google.api.http) = { + post: "/v1alpha1/lookupwatch" + body: "*" + }; + } } // WatchResourcesRequest starts a watch for specific permission updates // for the given resource and subject types. message WatchResourcesRequest { - // resource_object_type is the type of resource object for which we will // watch for changes. - string resource_object_type = 1 [ (validate.rules).string = { - pattern : "^([a-z][a-z0-9_]{1,61}[a-z0-9]/)*[a-z][a-z0-9_]{1,62}[a-z0-9]$", - max_bytes : 128, - } ]; + string resource_object_type = 1 [ + (validate.rules).string = { + pattern: "^([a-z][a-z0-9_]{1,61}[a-z0-9]/)*[a-z][a-z0-9_]{1,62}[a-z0-9]$" + max_bytes: 128 + }, + (buf.validate.field).string = { + pattern: "^([a-z][a-z0-9_]{1,61}[a-z0-9]/)*[a-z][a-z0-9_]{1,62}[a-z0-9]$" + max_bytes: 128 + } + ]; // permission is the name of the permission or relation for which we will // watch for changes. - string permission = 2 [ (validate.rules).string = { - pattern : "^[a-z][a-z0-9_]{1,62}[a-z0-9]$", - max_bytes : 64, - } ]; + string permission = 2 [ + (validate.rules).string = { + pattern: "^[a-z][a-z0-9_]{1,62}[a-z0-9]$" + max_bytes: 64 + }, + (buf.validate.field).string = { + pattern: "^[a-z][a-z0-9_]{1,62}[a-z0-9]$" + max_bytes: 64 + } + ]; // subject_object_type is the type of the subject resource for which we will // watch for changes. @@ -56,7 +65,6 @@ message WatchResourcesRequest { // PermissionUpdate represents a single permission update for a specific // subject's permissions. message PermissionUpdate { - // todo: work this into the v1 core API at some point since it's used // across services. enum Permissionship { @@ -80,4 +88,4 @@ message PermissionUpdate { message WatchResourcesResponse { repeated PermissionUpdate updates = 1; authzed.api.v1.ZedToken changes_through = 2; -} \ No newline at end of file +} diff --git a/buf.lock b/buf.lock index e098f10..35335dc 100644 --- a/buf.lock +++ b/buf.lock @@ -1,12 +1,15 @@ # Generated by buf. DO NOT EDIT. version: v2 deps: + - name: buf.build/bufbuild/protovalidate + commit: 5a7b106cbb87462d9a8c9ffecdbd2e38 + digest: b5:0f2dc6c9453e9cc9e9f36807aaa5f94022e837d91fef4dcaeed79a35c0843cc64eba28ff077aab24da3b2cb12639ad256246f9f9a36c033b99d5754b19996b7e - name: buf.build/envoyproxy/protoc-gen-validate - commit: 45685e052c7e406b9fbd441fc7a568a5 - digest: b5:63939effe0c64a94cd3151770b73007e43c9aeff31dcb24737fb11750dcaaca99338df3c1e5513828a685c743712e59ce283e046c27725e96928d200492bb6ec + commit: daf171c6cdb54629b5f51e345a79e4dd + digest: b5:c745e1521879f43740230b1df673d0729f55704efefdcfc489d4a0a2d40c92a26cacfeab62813403040a8b180142d53b398c7ca784a065e43823605ee49681de - name: buf.build/googleapis/googleapis - commit: 62f35d8aed1149c291d606d958a7ce32 - digest: b5:d66bf04adc77a0870bdc9328aaf887c7188a36fb02b83a480dc45ef9dc031b4d39fc6e9dc6435120ccf4fe5bfd5c6cb6592533c6c316595571f9a31420ab47fe + commit: c0913f24652a4cfc95f77d97443a5005 + digest: b5:4edb1480036c60f7867d75417d7faa87c851c96a4988a9746058a24e8e9bb4978daed0af35d57f6043de5a60355978dceaaa93dc992be99193260ac8823cbb8f - name: buf.build/grpc-ecosystem/grpc-gateway - commit: bc28b723cd774c32b6fbc77621518765 - digest: b5:a613f827fa6ff35a4f5e87e80e35ac6b35e5792cc9c5a658351072777d88c6d4df785a0c14889090db11667cf5463d122c7193b3719c7861d3e5747c22ce1381 + commit: a48fcebcf8f140dd9d09359b9bb185a4 + digest: b5:330af8a71b579ab96c4f3ee26929d1a68a5a9e986c7cfe0a898591fc514216bb6e723dc04c74d90fdee3f3f14f9100a54b4f079eb273e6e7213f0d5baca36ff8 diff --git a/buf.yaml b/buf.yaml index ad6a3f7..d9f1b0c 100644 --- a/buf.yaml +++ b/buf.yaml @@ -2,6 +2,7 @@ version: "v2" name: "buf.build/authzed/api" deps: + - "buf.build/envoyproxy/protoc-gen-validate" - "buf.build/bufbuild/protovalidate" - "buf.build/googleapis/googleapis" - "buf.build/grpc-ecosystem/grpc-gateway" From 98d1b668197fd00e0a8e8ba9680aa548c0bb4392 Mon Sep 17 00:00:00 2001 From: Tanner Stirrat Date: Thu, 21 Nov 2024 14:05:05 -0700 Subject: [PATCH 3/7] Bump buf version used in lint --- .github/workflows/lint.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/lint.yaml b/.github/workflows/lint.yaml index 43fddf7..730a69b 100644 --- a/.github/workflows/lint.yaml +++ b/.github/workflows/lint.yaml @@ -17,7 +17,7 @@ jobs: - uses: "authzed/actions/yaml-lint@main" - uses: "bufbuild/buf-setup-action@v1.32.2" with: - version: "1.30.0" + version: "1.46.2" - uses: "bufbuild/buf-lint-action@v1" - uses: "bufbuild/buf-breaking-action@v1" if: "github.event_name == 'pull_request'" From 645530775302d80e8d03ea845a810322cb46afa5 Mon Sep 17 00:00:00 2001 From: Tanner Stirrat Date: Thu, 21 Nov 2024 14:18:02 -0700 Subject: [PATCH 4/7] Use most recent version of buf --- .github/workflows/lint.yaml | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/.github/workflows/lint.yaml b/.github/workflows/lint.yaml index 730a69b..cea4640 100644 --- a/.github/workflows/lint.yaml +++ b/.github/workflows/lint.yaml @@ -15,9 +15,7 @@ jobs: steps: - uses: "actions/checkout@v3" - uses: "authzed/actions/yaml-lint@main" - - uses: "bufbuild/buf-setup-action@v1.32.2" - with: - version: "1.46.2" + - uses: "bufbuild/buf-setup-action@v1.47.2" - uses: "bufbuild/buf-lint-action@v1" - uses: "bufbuild/buf-breaking-action@v1" if: "github.event_name == 'pull_request'" From 0f29d31a7744a8d1887449af5793c71968e94283 Mon Sep 17 00:00:00 2001 From: Tanner Stirrat Date: Fri, 22 Nov 2024 12:37:18 -0700 Subject: [PATCH 5/7] Bump action versions, use github token --- .github/workflows/lint.yaml | 4 +++- .github/workflows/release.yaml | 6 +++--- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/.github/workflows/lint.yaml b/.github/workflows/lint.yaml index cea4640..047edf0 100644 --- a/.github/workflows/lint.yaml +++ b/.github/workflows/lint.yaml @@ -13,9 +13,11 @@ jobs: name: "Lint & Publish Draft/Branch" runs-on: "ubuntu-latest" steps: - - uses: "actions/checkout@v3" + - uses: "actions/checkout@v4" - uses: "authzed/actions/yaml-lint@main" - uses: "bufbuild/buf-setup-action@v1.47.2" + with: + github_token: "${{ github.token }}" - uses: "bufbuild/buf-lint-action@v1" - uses: "bufbuild/buf-breaking-action@v1" if: "github.event_name == 'pull_request'" diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index 14179e3..ce840c5 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -9,10 +9,10 @@ jobs: name: "Push BSR tag" runs-on: "ubuntu-latest" steps: - - uses: "actions/checkout@v3" - - uses: "bufbuild/buf-setup-action@v1.32.2" + - uses: "actions/checkout@v4" + - uses: "bufbuild/buf-setup-action@v1.47.2" with: - version: "1.30.0" + github_token: "${{ github.token }}" - name: "push release name to BSR" run: "buf push --tag ${{ github.ref_name }}" From 5fc57d9c4f291e968a69a583ac07f468953c59c7 Mon Sep 17 00:00:00 2001 From: Tanner Stirrat Date: Wed, 12 Mar 2025 16:10:22 -0600 Subject: [PATCH 6/7] Fix merge conflicts --- authzed/api/v1/core.proto | 20 +---- authzed/api/v1/debug.proto | 7 +- authzed/api/v1/experimental_service.proto | 93 ++--------------------- authzed/api/v1/permission_service.proto | 31 ++++---- authzed/api/v1/schema_service.proto | 13 +--- 5 files changed, 29 insertions(+), 135 deletions(-) diff --git a/authzed/api/v1/core.proto b/authzed/api/v1/core.proto index 314fcf4..0bba560 100644 --- a/authzed/api/v1/core.proto +++ b/authzed/api/v1/core.proto @@ -1,22 +1,14 @@ syntax = "proto3"; package authzed.api.v1; -import "buf/validate/validate.proto"; -import "google/protobuf/struct.proto"; -import "validate/validate.proto"; - option go_package = "github.com/authzed/authzed-go/proto/authzed/api/v1"; -option java_multiple_files = true; option java_package = "com.authzed.api.v1"; option java_multiple_files = true; +import "buf/validate/validate.proto"; import "google/protobuf/struct.proto"; import "google/protobuf/timestamp.proto"; import "validate/validate.proto"; -option java_multiple_files = true; - -import "google/protobuf/struct.proto"; -import "validate/validate.proto"; // Relationship specifies how a resource relates to a subject. Relationships // form the data for the graph over which all permissions questions are @@ -46,18 +38,14 @@ message Relationship { (buf.validate.field).required = true ]; - // optional_caveat is a reference to a the caveat that must be enforced over the relationship. - ContextualizedCaveat optional_caveat = 4 [ (validate.rules).message.required = false ]; - - // optional_expires_at is the time at which the relationship expires, if any. - google.protobuf.Timestamp optional_expires_at = 5; - // optional_caveat is a reference to a the caveat that must be enforced over the relationship - ContextualizedCaveat optional_caveat = 4 [ (validate.rules).message.required = false ]; // optional_caveat is a reference to a the caveat that must be enforced over the relationship ContextualizedCaveat optional_caveat = 4 [ (validate.rules).message.required = false, (buf.validate.field).required = false ]; + + // optional_expires_at is the time at which the relationship expires, if any. + google.protobuf.Timestamp optional_expires_at = 5; } // ContextualizedCaveat represents a reference to a caveat to be used by caveated relationships. diff --git a/authzed/api/v1/debug.proto b/authzed/api/v1/debug.proto index 6bdbe37..4c95d16 100644 --- a/authzed/api/v1/debug.proto +++ b/authzed/api/v1/debug.proto @@ -3,18 +3,14 @@ package authzed.api.v1; import "authzed/api/v1/core.proto"; import "buf/validate/validate.proto"; -import "google/protobuf/duration.proto"; -import "google/protobuf/struct.proto"; import "validate/validate.proto"; import "google/protobuf/struct.proto"; import "google/protobuf/duration.proto"; import "google/protobuf/timestamp.proto"; -import "google/protobuf/struct.proto"; -import "google/protobuf/duration.proto"; option go_package = "github.com/authzed/authzed-go/proto/authzed/api/v1"; -option java_multiple_files = true; option java_package = "com.authzed.api.v1"; +option java_multiple_files = true; // DebugInformation defines debug information returned by an API call in a footer when // requested with a specific debugging header. @@ -53,7 +49,6 @@ message CheckDebugTrace { // resource holds the resource on which the Check was performed. // for batched calls, the object_id field contains a comma-separated list of object IDs // for all the resources checked in the batch. - ObjectReference resource = 1 [(validate.rules).message.required = true]; ObjectReference resource = 1 [ (validate.rules).message.required = true, (buf.validate.field).required = true diff --git a/authzed/api/v1/experimental_service.proto b/authzed/api/v1/experimental_service.proto index d5c482c..16f1838 100644 --- a/authzed/api/v1/experimental_service.proto +++ b/authzed/api/v1/experimental_service.proto @@ -1,17 +1,18 @@ syntax = "proto3"; package authzed.api.v1; -import "authzed/api/v1/core.proto"; -import "authzed/api/v1/permission_service.proto"; -import "buf/validate/validate.proto"; +option go_package = "github.com/authzed/authzed-go/proto/authzed/api/v1"; +option java_package = "com.authzed.api.v1"; +option java_multiple_files = true; + import "google/api/annotations.proto"; +import "validate/validate.proto"; +import "buf/validate/validate.proto"; import "google/protobuf/struct.proto"; import "google/rpc/status.proto"; -import "validate/validate.proto"; -option go_package = "github.com/authzed/authzed-go/proto/authzed/api/v1"; -option java_multiple_files = true; -option java_package = "com.authzed.api.v1"; +import "authzed/api/v1/core.proto"; +import "authzed/api/v1/permission_service.proto"; // ExperimentalService exposes a number of APIs that are currently being // prototyped and tested for future inclusion in the stable API. @@ -61,23 +62,6 @@ service ExperimentalService { }; option deprecated = true; } - // EXPERIMENTAL: ReflectSchema is an API that allows clients to reflect the schema stored in - // SpiceDB. This is useful for clients that need to introspect the schema of a SpiceDB instance. - rpc ExperimentalReflectSchema(ExperimentalReflectSchemaRequest) - returns (ExperimentalReflectSchemaResponse) { - option (google.api.http) = { - post: "/v1/experimental/reflectschema" - body: "*" - }; - } - // EXPERIMENTAL: ReflectSchema is an API that allows clients to reflect the schema stored in - // SpiceDB. This is useful for clients that need to introspect the schema of a SpiceDB instance. - rpc ExperimentalReflectSchema(ExperimentalReflectSchemaRequest) returns (ExperimentalReflectSchemaResponse) { - option (google.api.http) = { - post: "/v1/experimental/reflectschema" - body: "*" - }; - } // DEPRECATED: Promoted to ComputablePermissions in the stable API. rpc ExperimentalComputablePermissions(ExperimentalComputablePermissionsRequest) @@ -98,48 +82,6 @@ service ExperimentalService { }; option deprecated = true; } - // EXPERIMENTAL: ComputablePermissions is an API that allows clients to request the set of - // permissions that compute based off a relation. For example, if a schema has a relation - // `viewer` and a permission `view` defined as `permission view = viewer + editor`, then the - // computable permissions for the relation `viewer` will include `view`. - rpc ExperimentalComputablePermissions(ExperimentalComputablePermissionsRequest) - returns (ExperimentalComputablePermissionsResponse) { - option (google.api.http) = { - post: "/v1/experimental/permissions/computable" - body: "*" - }; - } - - // EXPERIMENTAL: DependentRelations is an API that allows clients to request the set of - // relations and permissions that used to compute a permission, recursively. It is the - // inverse of the ComputablePermissions API. - rpc ExperimentalDependentRelations(ExperimentalDependentRelationsRequest) - returns (ExperimentalDependentRelationsResponse) { - option (google.api.http) = { - post: "/v1/experimental/permissions/dependent" - body: "*" - }; - } - // EXPERIMENTAL: ComputablePermissions is an API that allows clients to request the set of - // permissions that compute based off a relation. For example, if a schema has a relation - // `viewer` and a permission `view` defined as `permission view = viewer + editor`, then the - // computable permissions for the relation `viewer` will include `view`. - rpc ExperimentalComputablePermissions(ExperimentalComputablePermissionsRequest) returns (ExperimentalComputablePermissionsResponse) { - option (google.api.http) = { - post: "/v1/experimental/permissions/computable" - body: "*" - }; - } - - // EXPERIMENTAL: DependentRelations is an API that allows clients to request the set of - // relations and permissions that used to compute a permission, recursively. It is the - // inverse of the ComputablePermissions API. - rpc ExperimentalDependentRelations(ExperimentalDependentRelationsRequest) returns (ExperimentalDependentRelationsResponse) { - option (google.api.http) = { - post: "/v1/experimental/permissions/dependent" - body: "*" - }; - } // DEPRECATED: Promoted to DiffSchema in the stable API. rpc ExperimentalDiffSchema(ExperimentalDiffSchemaRequest) @@ -150,25 +92,6 @@ service ExperimentalService { }; option deprecated = true; } - // EXPERIMENTAL: DiffSchema is an API that allows clients to request the difference between the - // specified schema and the schema stored in SpiceDB. This is useful for clients that need to - // introspect the schema of a SpiceDB instance. - rpc ExperimentalDiffSchema(ExperimentalDiffSchemaRequest) - returns (ExperimentalDiffSchemaResponse) { - option (google.api.http) = { - post: "/v1/experimental/diffschema" - body: "*" - }; - } - // EXPERIMENTAL: DiffSchema is an API that allows clients to request the difference between the - // specified schema and the schema stored in SpiceDB. This is useful for clients that need to - // introspect the schema of a SpiceDB instance. - rpc ExperimentalDiffSchema(ExperimentalDiffSchemaRequest) returns (ExperimentalDiffSchemaResponse) { - option (google.api.http) = { - post: "/v1/experimental/diffschema" - body: "*" - }; - } // EXPERIMENTAL: RegisterRelationshipCounter registers a new filter for counting relationships. A filter must be registered before // a count can be requested. diff --git a/authzed/api/v1/permission_service.proto b/authzed/api/v1/permission_service.proto index ffe66c1..0bdd5cb 100644 --- a/authzed/api/v1/permission_service.proto +++ b/authzed/api/v1/permission_service.proto @@ -1,18 +1,19 @@ syntax = "proto3"; package authzed.api.v1; -import "authzed/api/v1/core.proto"; -import "authzed/api/v1/debug.proto"; -import "buf/validate/validate.proto"; -import "google/api/annotations.proto"; +option go_package = "github.com/authzed/authzed-go/proto/authzed/api/v1"; +option java_package = "com.authzed.api.v1"; +option java_multiple_files = true; + import "google/protobuf/struct.proto"; +import "google/api/annotations.proto"; import "google/rpc/status.proto"; import "google/protobuf/timestamp.proto"; import "validate/validate.proto"; +import "buf/validate/validate.proto"; -option go_package = "github.com/authzed/authzed-go/proto/authzed/api/v1"; -option java_multiple_files = true; -option java_package = "com.authzed.api.v1"; +import "authzed/api/v1/core.proto"; +import "authzed/api/v1/debug.proto"; // PermissionsService implements a set of RPCs that perform operations on // relationships and permissions. @@ -531,16 +532,15 @@ message CheckPermissionResponse { message CheckBulkPermissionsRequest { Consistency consistency = 1; + repeated CheckBulkPermissionsRequestItem items = 2 [ + (validate.rules).repeated.items.message.required = true, + (buf.validate.field).repeated.items.required = true + ]; // with_tracing, if true, indicates that each response should include a debug trace. // This can be useful for debugging and performance analysis, but adds a small amount // of compute overhead to the request. bool with_tracing = 3; - repeated CheckBulkPermissionsRequestItem items = 2 [(validate.rules).repeated.items.message.required = true]; - repeated CheckBulkPermissionsRequestItem items = 2 [ - (validate.rules).repeated.items.message.required = true, - (buf.validate.field).repeated.items.required = true - ]; } message CheckBulkPermissionsRequestItem { @@ -603,14 +603,13 @@ message CheckBulkPermissionsResponseItem { } ]; - - // debug_trace is the debugging trace of this check, if requested. - DebugInformation debug_trace = 3; - PartialCaveatInfo partial_caveat_info = 2 [(validate.rules).message.required = false]; PartialCaveatInfo partial_caveat_info = 2 [ (validate.rules).message.required = false, (buf.validate.field).required = false ]; + + // debug_trace is the debugging trace of this check, if requested. + DebugInformation debug_trace = 3; } // ExpandPermissionTreeRequest returns a tree representing the expansion of all diff --git a/authzed/api/v1/schema_service.proto b/authzed/api/v1/schema_service.proto index 8908ce9..9e9bcd5 100644 --- a/authzed/api/v1/schema_service.proto +++ b/authzed/api/v1/schema_service.proto @@ -1,27 +1,16 @@ syntax = "proto3"; package authzed.api.v1; -import "authzed/api/v1/core.proto"; -import "buf/validate/validate.proto"; -import "google/api/annotations.proto"; -import "validate/validate.proto"; - option go_package = "github.com/authzed/authzed-go/proto/authzed/api/v1"; -option java_multiple_files = true; option java_package = "com.authzed.api.v1"; option java_multiple_files = true; import "google/api/annotations.proto"; import "validate/validate.proto"; +import "buf/validate/validate.proto"; import "authzed/api/v1/core.proto"; import "authzed/api/v1/permission_service.proto"; -option java_multiple_files = true; - -import "google/api/annotations.proto"; -import "validate/validate.proto"; - -import "authzed/api/v1/core.proto"; // SchemaService implements operations on a Permissions System's Schema. service SchemaService { From 7ac29683aadb1b24a447d7b87f8d8877033f617f Mon Sep 17 00:00:00 2001 From: Tanner Stirrat Date: Wed, 12 Mar 2025 16:21:39 -0600 Subject: [PATCH 7/7] Format --- .github/workflows/lint.yaml | 37 +++++------ .github/workflows/release.yaml | 10 +-- authzed/api/v1/core.proto | 8 +-- authzed/api/v1/debug.proto | 6 +- authzed/api/v1/experimental_service.proto | 77 +++++++++++------------ authzed/api/v1/permission_service.proto | 17 +++-- authzed/api/v1/schema_service.proto | 75 +++++++++++----------- buf.lock | 12 ++-- 8 files changed, 109 insertions(+), 133 deletions(-) diff --git a/.github/workflows/lint.yaml b/.github/workflows/lint.yaml index 047edf0..46b2cb2 100644 --- a/.github/workflows/lint.yaml +++ b/.github/workflows/lint.yaml @@ -8,6 +8,17 @@ on: pull_request: branches: - "*" + types: + # This makes the buf checks run again when attributes of the PRs change. + - "ready_for_review" + - "labeled" + - "unlabeled" + # These are the defaults + - "opened" + - "synchronize" + - "reopened" + + jobs: lint: name: "Lint & Publish Draft/Branch" @@ -15,27 +26,7 @@ jobs: steps: - uses: "actions/checkout@v4" - uses: "authzed/actions/yaml-lint@main" - - uses: "bufbuild/buf-setup-action@v1.47.2" + - uses: "bufbuild/buf-action@v1" with: - github_token: "${{ github.token }}" - - uses: "bufbuild/buf-lint-action@v1" - - uses: "bufbuild/buf-breaking-action@v1" - if: "github.event_name == 'pull_request'" - env: - BUF_INPUT_HTTPS_USERNAME: "${{ github.actor }}" - BUF_INPUT_HTTPS_PASSWORD: "${{ github.token }}" - with: - against: "https://github.com/authzed/api.git#branch=main" - buf_token: "${{ secrets.BUF_REGISTRY_TOKEN }}" - - name: "Push to BSR a Draft" - if: "github.event_name == 'push' && github.ref == 'refs/heads/main'" - shell: "bash" - env: - BUF_TOKEN: "${{ secrets.BUF_REGISTRY_TOKEN }}" - run: "buf push --draft ${{ github.sha }}" - - name: "Push to BSR a Branch" - if: "github.event_name == 'push' && github.ref != 'refs/heads/main'" - shell: "bash" - env: - BUF_TOKEN: "${{ secrets.BUF_REGISTRY_TOKEN }}" - run: "buf push --branch ${{ github.sha }}" + token: "${{ secrets.BUF_REGISTRY_TOKEN }}" + breaking_against: "https://github.com/authzed/api.git#branch=main" diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index ce840c5..1498eb0 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -10,11 +10,7 @@ jobs: runs-on: "ubuntu-latest" steps: - uses: "actions/checkout@v4" - - uses: "bufbuild/buf-setup-action@v1.47.2" + - uses: "bufbuild/buf-action@v1" with: - github_token: "${{ github.token }}" - - name: "push release name to BSR" - run: - "buf push --tag ${{ github.ref_name }}" - env: - BUF_TOKEN: "${{ secrets.BUF_REGISTRY_TOKEN }}" + token: "${{ secrets.BUF_REGISTRY_TOKEN }}" + breaking_against: "https://github.com/authzed/api.git#branch=main" diff --git a/authzed/api/v1/core.proto b/authzed/api/v1/core.proto index 0bba560..fd8908b 100644 --- a/authzed/api/v1/core.proto +++ b/authzed/api/v1/core.proto @@ -1,15 +1,15 @@ syntax = "proto3"; package authzed.api.v1; -option go_package = "github.com/authzed/authzed-go/proto/authzed/api/v1"; -option java_package = "com.authzed.api.v1"; -option java_multiple_files = true; - import "buf/validate/validate.proto"; import "google/protobuf/struct.proto"; import "google/protobuf/timestamp.proto"; import "validate/validate.proto"; +option go_package = "github.com/authzed/authzed-go/proto/authzed/api/v1"; +option java_multiple_files = true; +option java_package = "com.authzed.api.v1"; + // Relationship specifies how a resource relates to a subject. Relationships // form the data for the graph over which all permissions questions are // answered. diff --git a/authzed/api/v1/debug.proto b/authzed/api/v1/debug.proto index 4c95d16..03ae189 100644 --- a/authzed/api/v1/debug.proto +++ b/authzed/api/v1/debug.proto @@ -3,14 +3,14 @@ package authzed.api.v1; import "authzed/api/v1/core.proto"; import "buf/validate/validate.proto"; -import "validate/validate.proto"; -import "google/protobuf/struct.proto"; import "google/protobuf/duration.proto"; +import "google/protobuf/struct.proto"; import "google/protobuf/timestamp.proto"; +import "validate/validate.proto"; option go_package = "github.com/authzed/authzed-go/proto/authzed/api/v1"; -option java_package = "com.authzed.api.v1"; option java_multiple_files = true; +option java_package = "com.authzed.api.v1"; // DebugInformation defines debug information returned by an API call in a footer when // requested with a specific debugging header. diff --git a/authzed/api/v1/experimental_service.proto b/authzed/api/v1/experimental_service.proto index 16f1838..2cc818f 100644 --- a/authzed/api/v1/experimental_service.proto +++ b/authzed/api/v1/experimental_service.proto @@ -1,18 +1,17 @@ syntax = "proto3"; package authzed.api.v1; -option go_package = "github.com/authzed/authzed-go/proto/authzed/api/v1"; -option java_package = "com.authzed.api.v1"; -option java_multiple_files = true; - -import "google/api/annotations.proto"; -import "validate/validate.proto"; +import "authzed/api/v1/core.proto"; +import "authzed/api/v1/permission_service.proto"; import "buf/validate/validate.proto"; +import "google/api/annotations.proto"; import "google/protobuf/struct.proto"; import "google/rpc/status.proto"; +import "validate/validate.proto"; -import "authzed/api/v1/core.proto"; -import "authzed/api/v1/permission_service.proto"; +option go_package = "github.com/authzed/authzed-go/proto/authzed/api/v1"; +option java_multiple_files = true; +option java_package = "com.authzed.api.v1"; // ExperimentalService exposes a number of APIs that are currently being // prototyped and tested for future inclusion in the stable API. @@ -54,44 +53,40 @@ service ExperimentalService { } // DEPRECATED: Promoted to ReflectSchema in the stable API. - rpc ExperimentalReflectSchema(ExperimentalReflectSchemaRequest) - returns (ExperimentalReflectSchemaResponse) { - option (google.api.http) = { - post: "/v1/experimental/reflectschema" - body: "*" - }; - option deprecated = true; - } + rpc ExperimentalReflectSchema(ExperimentalReflectSchemaRequest) returns (ExperimentalReflectSchemaResponse) { + option (google.api.http) = { + post: "/v1/experimental/reflectschema" + body: "*" + }; + option deprecated = true; + } // DEPRECATED: Promoted to ComputablePermissions in the stable API. - rpc ExperimentalComputablePermissions(ExperimentalComputablePermissionsRequest) - returns (ExperimentalComputablePermissionsResponse) { - option (google.api.http) = { - post: "/v1/experimental/permissions/computable" - body: "*" - }; - option deprecated = true; - } - + rpc ExperimentalComputablePermissions(ExperimentalComputablePermissionsRequest) returns (ExperimentalComputablePermissionsResponse) { + option (google.api.http) = { + post: "/v1/experimental/permissions/computable" + body: "*" + }; + option deprecated = true; + } + // DEPRECATED: Promoted to DependentRelations in the stable API. - rpc ExperimentalDependentRelations(ExperimentalDependentRelationsRequest) - returns (ExperimentalDependentRelationsResponse) { - option (google.api.http) = { - post: "/v1/experimental/permissions/dependent" - body: "*" - }; - option deprecated = true; - } + rpc ExperimentalDependentRelations(ExperimentalDependentRelationsRequest) returns (ExperimentalDependentRelationsResponse) { + option (google.api.http) = { + post: "/v1/experimental/permissions/dependent" + body: "*" + }; + option deprecated = true; + } // DEPRECATED: Promoted to DiffSchema in the stable API. - rpc ExperimentalDiffSchema(ExperimentalDiffSchemaRequest) - returns (ExperimentalDiffSchemaResponse) { - option (google.api.http) = { - post: "/v1/experimental/diffschema" - body: "*" - }; - option deprecated = true; - } + rpc ExperimentalDiffSchema(ExperimentalDiffSchemaRequest) returns (ExperimentalDiffSchemaResponse) { + option (google.api.http) = { + post: "/v1/experimental/diffschema" + body: "*" + }; + option deprecated = true; + } // EXPERIMENTAL: RegisterRelationshipCounter registers a new filter for counting relationships. A filter must be registered before // a count can be requested. diff --git a/authzed/api/v1/permission_service.proto b/authzed/api/v1/permission_service.proto index 0bdd5cb..9390611 100644 --- a/authzed/api/v1/permission_service.proto +++ b/authzed/api/v1/permission_service.proto @@ -1,19 +1,18 @@ syntax = "proto3"; package authzed.api.v1; -option go_package = "github.com/authzed/authzed-go/proto/authzed/api/v1"; -option java_package = "com.authzed.api.v1"; -option java_multiple_files = true; - -import "google/protobuf/struct.proto"; +import "authzed/api/v1/core.proto"; +import "authzed/api/v1/debug.proto"; +import "buf/validate/validate.proto"; import "google/api/annotations.proto"; -import "google/rpc/status.proto"; +import "google/protobuf/struct.proto"; import "google/protobuf/timestamp.proto"; +import "google/rpc/status.proto"; import "validate/validate.proto"; -import "buf/validate/validate.proto"; -import "authzed/api/v1/core.proto"; -import "authzed/api/v1/debug.proto"; +option go_package = "github.com/authzed/authzed-go/proto/authzed/api/v1"; +option java_multiple_files = true; +option java_package = "com.authzed.api.v1"; // PermissionsService implements a set of RPCs that perform operations on // relationships and permissions. diff --git a/authzed/api/v1/schema_service.proto b/authzed/api/v1/schema_service.proto index 9e9bcd5..073d428 100644 --- a/authzed/api/v1/schema_service.proto +++ b/authzed/api/v1/schema_service.proto @@ -1,16 +1,15 @@ syntax = "proto3"; package authzed.api.v1; -option go_package = "github.com/authzed/authzed-go/proto/authzed/api/v1"; -option java_package = "com.authzed.api.v1"; -option java_multiple_files = true; - +import "authzed/api/v1/core.proto"; +import "authzed/api/v1/permission_service.proto"; +import "buf/validate/validate.proto"; import "google/api/annotations.proto"; import "validate/validate.proto"; -import "buf/validate/validate.proto"; -import "authzed/api/v1/core.proto"; -import "authzed/api/v1/permission_service.proto"; +option go_package = "github.com/authzed/authzed-go/proto/authzed/api/v1"; +option java_multiple_files = true; +option java_package = "com.authzed.api.v1"; // SchemaService implements operations on a Permissions System's Schema. service SchemaService { @@ -36,46 +35,42 @@ service SchemaService { // ReflectSchema reflects the current schema stored in SpiceDB, returning a structural // form of the schema for use by client tooling. - rpc ReflectSchema(ReflectSchemaRequest) - returns (ReflectSchemaResponse) { - option (google.api.http) = { - post: "/v1/schema/reflectschema" - body: "*" - }; - } + rpc ReflectSchema(ReflectSchemaRequest) returns (ReflectSchemaResponse) { + option (google.api.http) = { + post: "/v1/schema/reflectschema" + body: "*" + }; + } // ComputablePermissions returns the set of permissions that compute based off a relation // in the current schema. For example, if the schema has a relation `viewer` and a permission // `view` defined as `permission view = viewer + editor`, then the // computable permissions for the relation `viewer` will include `view`. - rpc ComputablePermissions(ComputablePermissionsRequest) - returns (ComputablePermissionsResponse) { - option (google.api.http) = { - post: "/v1/schema/permissions/computable" - body: "*" - }; - } - + rpc ComputablePermissions(ComputablePermissionsRequest) returns (ComputablePermissionsResponse) { + option (google.api.http) = { + post: "/v1/schema/permissions/computable" + body: "*" + }; + } + // DependentRelations returns the set of relations and permissions that used // to compute a permission, recursively, in the current schema. It is the // inverse of the ComputablePermissions API. - rpc DependentRelations(DependentRelationsRequest) - returns (DependentRelationsResponse) { - option (google.api.http) = { - post: "/v1/schema/permissions/dependent" - body: "*" - }; - } + rpc DependentRelations(DependentRelationsRequest) returns (DependentRelationsResponse) { + option (google.api.http) = { + post: "/v1/schema/permissions/dependent" + body: "*" + }; + } // DiffSchema returns the difference between the specified schema and the current // schema stored in SpiceDB. - rpc DiffSchema(DiffSchemaRequest) - returns (DiffSchemaResponse) { - option (google.api.http) = { - post: "/v1/schema/diffschema" - body: "*" - }; - } + rpc DiffSchema(DiffSchemaRequest) returns (DiffSchemaResponse) { + option (google.api.http) = { + post: "/v1/schema/diffschema" + body: "*" + }; + } } // ReadSchemaRequest returns the schema from the database. @@ -119,7 +114,7 @@ message WriteSchemaResponse { message ReflectSchemaRequest { Consistency consistency = 1; - + // optional_filters defines optional filters that are applied in // an OR fashion to the schema, before being returned repeated ReflectionSchemaFilter optional_filters = 2; @@ -158,7 +153,7 @@ message ReflectionDefinition { // comment is a human-readable comments on the definition. Will include // delimiter characters. string comment = 2; - + repeated ReflectionRelation relations = 3; repeated ReflectionPermission permissions = 4; } @@ -204,12 +199,12 @@ message ReflectionTypeReference { oneof typeref { // is_terminal_subject is true if the subject is terminal, meaning it is referenced directly vs a sub-relation. bool is_terminal_subject = 3; - + // optional_relation_name is the name of the relation that is applied to the subject, if any. string optional_relation_name = 4; // is_public_wildcard is true if the subject is a public wildcard. - bool is_public_wildcard = 5; + bool is_public_wildcard = 5; } } diff --git a/buf.lock b/buf.lock index 35335dc..f9989e7 100644 --- a/buf.lock +++ b/buf.lock @@ -2,14 +2,14 @@ version: v2 deps: - name: buf.build/bufbuild/protovalidate - commit: 5a7b106cbb87462d9a8c9ffecdbd2e38 - digest: b5:0f2dc6c9453e9cc9e9f36807aaa5f94022e837d91fef4dcaeed79a35c0843cc64eba28ff077aab24da3b2cb12639ad256246f9f9a36c033b99d5754b19996b7e + commit: 0409229c37804d6187ee0806eb4eebce + digest: b5:795db9d3a6e066dc61d99ac651fa7f136171869abe2211ca272dd84aada7bc4583b9508249fa5b61300a5b1fe8b6dbf6edbc088aa0345d1ccb9fff705e3d48e9 - name: buf.build/envoyproxy/protoc-gen-validate commit: daf171c6cdb54629b5f51e345a79e4dd digest: b5:c745e1521879f43740230b1df673d0729f55704efefdcfc489d4a0a2d40c92a26cacfeab62813403040a8b180142d53b398c7ca784a065e43823605ee49681de - name: buf.build/googleapis/googleapis - commit: c0913f24652a4cfc95f77d97443a5005 - digest: b5:4edb1480036c60f7867d75417d7faa87c851c96a4988a9746058a24e8e9bb4978daed0af35d57f6043de5a60355978dceaaa93dc992be99193260ac8823cbb8f + commit: 61b203b9a9164be9a834f58c37be6f62 + digest: b5:7811a98b35bd2e4ae5c3ac73c8b3d9ae429f3a790da15de188dc98fc2b77d6bb10e45711f14903af9553fa9821dff256054f2e4b7795789265bc476bec2f088c - name: buf.build/grpc-ecosystem/grpc-gateway - commit: a48fcebcf8f140dd9d09359b9bb185a4 - digest: b5:330af8a71b579ab96c4f3ee26929d1a68a5a9e986c7cfe0a898591fc514216bb6e723dc04c74d90fdee3f3f14f9100a54b4f079eb273e6e7213f0d5baca36ff8 + commit: 4c5ba75caaf84e928b7137ae5c18c26a + digest: b5:c113e62fb3b29289af785866cae062b55ec8ae19ab3f08f3004098928fbca657730a06810b2012951294326b95669547194fa84476b9e9b688d4f8bf77a0691d