From 439b86da9c12ddf5ba17b13fdacda9766a06806c Mon Sep 17 00:00:00 2001 From: Tanner Stirrat Date: Thu, 21 Nov 2024 13:39:15 -0700 Subject: [PATCH 1/6] 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 589873c08ab3c4a4609f02bbf7ff69c430db3e7b Mon Sep 17 00:00:00 2001 From: Tanner Stirrat Date: Thu, 21 Nov 2024 13:41:52 -0700 Subject: [PATCH 2/6] Run buf format --- .pre-commit-config.yaml | 2 +- .../api/materialize/v0/watchpermissions.proto | 2 +- .../materialize/v0/watchpermissionsets.proto | 28 +- authzed/api/v0/core.proto | 53 ++- authzed/api/v0/developer.proto | 6 +- authzed/api/v1/core.proto | 89 ++-- authzed/api/v1/debug.proto | 24 +- authzed/api/v1/error_reason.proto | 50 +-- authzed/api/v1/experimental_service.proto | 221 +++++----- authzed/api/v1/openapi.proto | 81 ++-- authzed/api/v1/permission_service.proto | 392 +++++++++--------- authzed/api/v1/schema_service.proto | 17 +- authzed/api/v1/watch_service.proto | 22 +- authzed/api/v1alpha1/schema.proto | 18 +- .../api/v1alpha1/watchresources_service.proto | 41 +- 15 files changed, 523 insertions(+), 523 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 378bf72..ae3e62e 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"). @@ -152,21 +152,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..eadb7e3 100644 --- a/authzed/api/v0/core.proto +++ b/authzed/api/v0/core.proto @@ -1,11 +1,11 @@ syntax = "proto3"; package authzed.api.v0; +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 +18,40 @@ 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]; + User user = 2 [(validate.rules).message.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 + }]; + 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 + }]; } 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 + }]; + string relation = 3 [(validate.rules).string = { + pattern: "^(\\.\\.\\.|[a-z][a-z0-9_]{1,62}[a-z0-9])$" + max_bytes: 64 + }]; } message User { oneof user_oneof { option (validate.required) = true; - ObjectAndRelation userset = 2 [ (validate.rules).message.required = true ]; + ObjectAndRelation userset = 2 [(validate.rules).message.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 1e67cab..891438b 100644 --- a/authzed/api/v1/core.proto +++ b/authzed/api/v1/core.proto @@ -1,31 +1,31 @@ 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 "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. 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]; // 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 + }]; // 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]; // 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 ]; + ContextualizedCaveat optional_caveat = 4 [(validate.rules).message.required = false]; } // ContextualizedCaveat represents a reference to a caveat to be used by caveated relationships. @@ -33,36 +33,36 @@ 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 + }]; // 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]; } // 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]; + string optional_relation = 2 [(validate.rules).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 + }]; + string object_id = 2 [(validate.rules).string = { + pattern: "^(([a-zA-Z0-9/_|\\-=+]{1,})|\\*)$" + max_bytes: 1024 + }]; } // ZedToken is used to provide causality metadata between Write and Check @@ -70,21 +70,18 @@ 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}]; } // 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 + }]; } - // RelationshipUpdate is used for mutating a single relationship within the // service. // @@ -103,8 +100,11 @@ 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] + }]; + Relationship relationship = 2 [(validate.rules).message.required = true]; } // PermissionRelationshipTree is used for representing a tree of a resource and @@ -138,12 +138,17 @@ 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] + }]; + repeated PermissionRelationshipTree children = 2 [(validate.rules).repeated.items.message.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 diff --git a/authzed/api/v1/debug.proto b/authzed/api/v1/debug.proto index 3f72f0a..8145746 100644 --- a/authzed/api/v1/debug.proto +++ b/authzed/api/v1/debug.proto @@ -2,13 +2,13 @@ syntax = "proto3"; package authzed.api.v1; import "authzed/api/v1/core.proto"; -import "validate/validate.proto"; -import "google/protobuf/struct.proto"; import "google/protobuf/duration.proto"; +import "google/protobuf/struct.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. @@ -45,21 +45,27 @@ message CheckDebugTrace { } // resource holds the resource on which the Check was performed. - ObjectReference resource = 1 [ (validate.rules).message.required = true ]; + ObjectReference resource = 1 [(validate.rules).message.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] + }]; // 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]; // 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] + }]; + // caveat_evaluation_info holds information about the caveat evaluated for this step of the trace. CaveatEvalInfo caveat_evaluation_info = 8; @@ -105,4 +111,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 d261f1d..a89d1a6 100644 --- a/authzed/api/v1/experimental_service.proto +++ b/authzed/api/v1/experimental_service.proto @@ -1,17 +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 "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,133 +21,122 @@ 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) { - option (google.api.http) = { - post: "/v1/experimental/permissions/bulkcheckpermission" - body: "*" - }; - option deprecated = true; - } + rpc BulkCheckPermission(BulkCheckPermissionRequest) returns (BulkCheckPermissionResponse) { + option (google.api.http) = { + post: "/v1/experimental/permissions/bulkcheckpermission" + 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: "*" - }; - } + rpc ExperimentalReflectSchema(ExperimentalReflectSchemaRequest) returns (ExperimentalReflectSchemaResponse) { + option (google.api.http) = { + post: "/v1/experimental/reflectschema" + 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: "*" - }; - } - + 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: "*" - }; - } + rpc ExperimentalDependentRelations(ExperimentalDependentRelationsRequest) returns (ExperimentalDependentRelationsResponse) { + option (google.api.http) = { + post: "/v1/experimental/permissions/dependent" + 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: "*" - }; - } + 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: "*" - }; - } + 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 + }]; // 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]; } 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 + }]; } message ExperimentalCountRelationshipsResponse { @@ -166,15 +154,15 @@ 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]; } 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 + }]; } message ExperimentalUnregisterRelationshipCounterResponse {} @@ -183,26 +171,29 @@ 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, + deprecated = true + ]; } message BulkCheckPermissionRequestItem { - ObjectReference resource = 1 [ (validate.rules).message.required = true ]; + 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, - } ]; + string permission = 2 [(validate.rules).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]; - google.protobuf.Struct context = 4 [ (validate.rules).message.required = false ]; + google.protobuf.Struct context = 4 [(validate.rules).message.required = false]; } message BulkCheckPermissionResponse { - ZedToken checked_at = 1 [ (validate.rules).message.required = false ]; + ZedToken checked_at = 1 [(validate.rules).message.required = false]; - repeated BulkCheckPermissionPair pairs = 2 [ (validate.rules).repeated .items.message.required = true ]; + repeated BulkCheckPermissionPair pairs = 2 [(validate.rules).repeated.items.message.required = true]; } message BulkCheckPermissionPair { @@ -214,9 +205,12 @@ 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] + }]; - PartialCaveatInfo partial_caveat_info = 2 [ (validate.rules).message.required = false ]; + PartialCaveatInfo partial_caveat_info = 2 [(validate.rules).message.required = false]; } // BulkImportRelationshipsRequest represents one batch of the streaming @@ -227,8 +221,7 @@ 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]; } // BulkImportRelationshipsResponse is returned on successful completion of the @@ -246,7 +239,7 @@ 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}]; // optional_cursor, if specified, indicates the cursor after which results // should resume being returned. The cursor can be found on the @@ -263,7 +256,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; } @@ -271,7 +264,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; @@ -310,7 +303,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; } @@ -356,12 +349,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 5e1b453..cc76f84 100644 --- a/authzed/api/v1/permission_service.proto +++ b/authzed/api/v1/permission_service.proto @@ -1,104 +1,95 @@ 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 "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/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 @@ -107,24 +98,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. @@ -136,7 +125,7 @@ message Consistency { // 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]; // 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 @@ -154,7 +143,7 @@ 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]; } } @@ -170,31 +159,30 @@ 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 + }]; // 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 + }]; // 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 + }]; // 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 + }]; // optional_subject_filter is the optional filter for the subjects of the relationships. SubjectFilter optional_subject_filter = 4; @@ -206,21 +194,21 @@ 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 + }]; } - 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 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 optional_subject_id = 2 [(validate.rules).string = { + pattern: "^(([a-zA-Z0-9/_|\\-=+]{1,})|\\*)?$" + max_bytes: 1024 + }]; RelationFilter optional_relation = 3; } @@ -232,14 +220,13 @@ 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]; // 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}]; // optional_cursor, if specified, indicates the cursor after which results should resume being returned. // The cursor can be found on the ReadRelationshipsResponse object. @@ -251,10 +238,10 @@ 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]; // relationship is the found relationship. - Relationship relationship = 2 [ (validate.rules).message.required = true ]; + Relationship relationship = 2 [(validate.rules).message.required = true]; // after_result_cursor holds a cursor that can be used to resume the ReadRelationships stream after this // result. @@ -276,8 +263,11 @@ 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] + }]; + RelationshipFilter filter = 2 [(validate.rules).message.required = true]; } // WriteRelationshipsRequest contains a list of Relationship mutations that @@ -286,20 +276,19 @@ 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]; - 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]; // 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]; } -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 @@ -307,19 +296,16 @@ 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]; - 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]; // 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}]; // 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. @@ -328,13 +314,13 @@ 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]; } 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; @@ -359,20 +345,20 @@ 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]; // 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 + }]; // 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]; // 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]; // 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 @@ -388,7 +374,7 @@ message CheckPermissionResponse { PERMISSIONSHIP_CONDITIONAL_PERMISSION = 3; } - ZedToken checked_at = 1 [ (validate.rules).message.required = false ]; + ZedToken checked_at = 1 [(validate.rules).message.required = false]; // Permissionship communicates whether or not the subject has the requested // permission or has a relationship with the given resource, over the given @@ -398,16 +384,19 @@ 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] + }]; // 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]; // debug_trace is the debugging trace of this check, if requested. DebugInformation debug_trace = 4; } -// 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. @@ -415,26 +404,26 @@ message CheckPermissionResponse { message CheckBulkPermissionsRequest { Consistency consistency = 1; - repeated CheckBulkPermissionsRequestItem items = 2 [ (validate.rules).repeated .items.message.required = true ]; + repeated CheckBulkPermissionsRequestItem items = 2 [(validate.rules).repeated.items.message.required = true]; } message CheckBulkPermissionsRequestItem { - ObjectReference resource = 1 [ (validate.rules).message.required = true ]; + 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, - } ]; + string permission = 2 [(validate.rules).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]; - google.protobuf.Struct context = 4 [ (validate.rules).message.required = false ]; + google.protobuf.Struct context = 4 [(validate.rules).message.required = false]; } message CheckBulkPermissionsResponse { - ZedToken checked_at = 1 [ (validate.rules).message.required = false ]; + ZedToken checked_at = 1 [(validate.rules).message.required = false]; - repeated CheckBulkPermissionsPair pairs = 2 [ (validate.rules).repeated .items.message.required = true ]; + repeated CheckBulkPermissionsPair pairs = 2 [(validate.rules).repeated.items.message.required = true]; } message CheckBulkPermissionsPair { @@ -446,9 +435,12 @@ 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] + }]; - PartialCaveatInfo partial_caveat_info = 2 [ (validate.rules).message.required = false ]; + PartialCaveatInfo partial_caveat_info = 2 [(validate.rules).message.required = false]; } // ExpandPermissionTreeRequest returns a tree representing the expansion of all @@ -462,14 +454,14 @@ 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]; // 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 + }]; } message ExpandPermissionTreeResponse { @@ -489,29 +481,29 @@ 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 + }]; // 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 + }]; // 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]; // 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]; // 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}]; // optional_cursor, if specified, indicates the cursor after which results should resume being returned. // The cursor can be found on the LookupResourcesResponse object. @@ -535,10 +527,13 @@ 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] + }]; // 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]; // after_result_cursor holds a cursor that can be used to resume the LookupResources stream after this // result. @@ -559,30 +554,30 @@ 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]; // 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 + }]; // 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 + }]; // 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 + }]; // 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]; // 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 @@ -604,7 +599,7 @@ 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}]; // optional_cursor, if specified, indicates the cursor after which results should resume being returned. // The cursor can be found on the LookupSubjectsResponse object. @@ -635,11 +630,20 @@ 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] + } + ]; // 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 + ]; // subject is the subject found, along with its permissionship. ResolvedSubject subject = 6; @@ -661,10 +665,13 @@ 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] + }]; // 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]; } // ImportBulkRelationshipsRequest represents one batch of the streaming @@ -675,8 +682,7 @@ 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]; } // ImportBulkRelationshipsResponse is returned on successful completion of the @@ -694,7 +700,7 @@ 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}]; // optional_cursor, if specified, indicates the cursor after which results // should resume being returned. The cursor can be found on the @@ -711,6 +717,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 08c3a66..876f79c 100644 --- a/authzed/api/v1/schema_service.proto +++ b/authzed/api/v1/schema_service.proto @@ -1,14 +1,13 @@ 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 "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/v1"; +option java_multiple_files = true; +option java_package = "com.authzed.api.v1"; // SchemaService implements operations on a Permissions System's Schema. service SchemaService { @@ -43,7 +42,7 @@ 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]; } // WriteSchemaRequest is the required data used to "upsert" the Schema of a @@ -51,12 +50,12 @@ 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]; // 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]; } diff --git a/authzed/api/v1/watch_service.proto b/authzed/api/v1/watch_service.proto index cc3b24d..7a7e54a 100644 --- a/authzed/api/v1/watch_service.proto +++ b/authzed/api/v1/watch_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 "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 +28,12 @@ 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, + (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 } ]; diff --git a/authzed/api/v1alpha1/schema.proto b/authzed/api/v1alpha1/schema.proto index 9cde043..046a6f4 100644 --- a/authzed/api/v1alpha1/schema.proto +++ b/authzed/api/v1alpha1/schema.proto @@ -1,11 +1,11 @@ syntax = "proto3"; package authzed.api.v1alpha1; +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 +13,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 +23,15 @@ 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 + }]; } // ReadSchemaResponse is the resulting data after having read the Object @@ -49,7 +49,7 @@ 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]; // 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..255944e 100644 --- a/authzed/api/v1alpha1/watchresources_service.proto +++ b/authzed/api/v1alpha1/watchresources_service.proto @@ -1,46 +1,42 @@ 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 "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 + }]; // 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 + }]; // subject_object_type is the type of the subject resource for which we will // watch for changes. @@ -56,7 +52,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 +75,4 @@ message PermissionUpdate { message WatchResourcesResponse { repeated PermissionUpdate updates = 1; authzed.api.v1.ZedToken changes_through = 2; -} \ No newline at end of file +} From cd5df346136bc8f2b0f677cfb80a212dca449570 Mon Sep 17 00:00:00 2001 From: Tanner Stirrat Date: Thu, 21 Nov 2024 13:51:05 -0700 Subject: [PATCH 3/6] Migrate files and re-add old validate temporarily --- authzed/api/v0/core.proto | 87 +++- authzed/api/v1/core.proto | 159 ++++-- authzed/api/v1/debug.proto | 40 +- authzed/api/v1/experimental_service.proto | 122 +++-- authzed/api/v1/permission_service.proto | 474 +++++++++++++----- authzed/api/v1/schema_service.proto | 16 +- authzed/api/v1/watch_service.proto | 8 + authzed/api/v1alpha1/schema.proto | 20 +- .../api/v1alpha1/watchresources_service.proto | 29 +- buf.lock | 15 +- buf.yaml | 1 + 11 files changed, 727 insertions(+), 244 deletions(-) diff --git a/authzed/api/v0/core.proto b/authzed/api/v0/core.proto index eadb7e3..6325396 100644 --- a/authzed/api/v0/core.proto +++ b/authzed/api/v0/core.proto @@ -1,6 +1,7 @@ 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"; @@ -18,40 +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 + ]; } } diff --git a/authzed/api/v1/core.proto b/authzed/api/v1/core.proto index 891438b..e3848b7 100644 --- a/authzed/api/v1/core.proto +++ b/authzed/api/v1/core.proto @@ -1,6 +1,7 @@ syntax = "proto3"; package authzed.api.v1; +import "buf/validate/validate.proto"; import "google/protobuf/struct.proto"; import "validate/validate.proto"; @@ -13,19 +14,34 @@ option java_package = "com.authzed.api.v1"; // 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]; + 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. @@ -33,36 +49,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 @@ -70,16 +116,25 @@ 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 @@ -100,11 +155,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 @@ -112,6 +176,7 @@ message RelationshipUpdate { message PermissionRelationshipTree { oneof tree_type { option (validate.required) = true; + option (buf.validate.oneof).required = true; AlgebraicSubjectSet intermediate = 1; DirectSubjectSet leaf = 2; @@ -138,11 +203,20 @@ 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. @@ -155,5 +229,8 @@ message DirectSubjectSet { 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 8145746..dfeb745 100644 --- a/authzed/api/v1/debug.proto +++ b/authzed/api/v1/debug.proto @@ -2,6 +2,7 @@ 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"; @@ -45,26 +46,44 @@ message CheckDebugTrace { } // resource holds the resource on which the Check was performed. - 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; @@ -75,6 +94,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; diff --git a/authzed/api/v1/experimental_service.proto b/authzed/api/v1/experimental_service.proto index a89d1a6..2e1b0b9 100644 --- a/authzed/api/v1/experimental_service.proto +++ b/authzed/api/v1/experimental_service.proto @@ -3,6 +3,7 @@ package authzed.api.v1; 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"; @@ -119,24 +120,39 @@ service ExperimentalService { 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 { @@ -154,15 +170,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 {} @@ -173,27 +198,49 @@ message BulkCheckPermissionRequest { 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]; + 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 - }]; + 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 { @@ -205,12 +252,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 @@ -221,7 +277,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 @@ -239,7 +298,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 diff --git a/authzed/api/v1/permission_service.proto b/authzed/api/v1/permission_service.proto index cc76f84..243a514 100644 --- a/authzed/api/v1/permission_service.proto +++ b/authzed/api/v1/permission_service.proto @@ -3,6 +3,7 @@ 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"; import "google/protobuf/struct.proto"; import "google/rpc/status.proto"; @@ -122,10 +123,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 @@ -143,7 +148,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 + ]; } } @@ -159,30 +167,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; @@ -194,21 +226,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 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 - }]; + 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; } @@ -220,13 +270,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. @@ -238,10 +294,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. @@ -263,11 +325,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 @@ -276,14 +347,23 @@ 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 { @@ -296,16 +376,25 @@ message WriteRelationshipsResponse { // 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. @@ -314,7 +403,10 @@ 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 { @@ -345,20 +437,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 @@ -374,7 +481,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 @@ -384,13 +494,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; @@ -404,26 +523,50 @@ message CheckPermissionResponse { message CheckBulkPermissionsRequest { Consistency consistency = 1; - 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]; + 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 - }]; + 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]; + 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]; + repeated CheckBulkPermissionsPair pairs = 2 [ + (validate.rules).repeated.items.message.required = true, + (buf.validate.field).repeated.items.required = true + ]; } message CheckBulkPermissionsPair { @@ -435,12 +578,21 @@ 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]; + PartialCaveatInfo partial_caveat_info = 2 [ + (validate.rules).message.required = false, + (buf.validate.field).required = false + ]; } // ExpandPermissionTreeRequest returns a tree representing the expansion of all @@ -454,14 +606,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 { @@ -481,29 +642,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. @@ -527,13 +709,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. @@ -554,30 +745,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 @@ -599,7 +814,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. @@ -635,6 +853,10 @@ message LookupSubjectsResponse { (validate.rules).enum = { defined_only: true not_in: [0] + }, + (buf.validate.field).enum = { + defined_only: true + not_in: [0] } ]; @@ -642,7 +864,8 @@ message LookupSubjectsResponse { // deprecated: use `subject.partial_caveat_info` PartialCaveatInfo partial_caveat_info = 5 [ deprecated = true, - (validate.rules).message.required = false + (validate.rules).message.required = false, + (buf.validate.field).required = false ]; // subject is the subject found, along with its permissionship. @@ -665,13 +888,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 @@ -682,7 +914,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 @@ -700,7 +935,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 diff --git a/authzed/api/v1/schema_service.proto b/authzed/api/v1/schema_service.proto index 876f79c..3ebaa10 100644 --- a/authzed/api/v1/schema_service.proto +++ b/authzed/api/v1/schema_service.proto @@ -2,6 +2,7 @@ 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"; @@ -42,7 +43,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 @@ -50,12 +54,18 @@ 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]; + ZedToken written_at = 1 [ + (validate.rules).message.required = true, + (buf.validate.field).required = true + ]; } diff --git a/authzed/api/v1/watch_service.proto b/authzed/api/v1/watch_service.proto index 7a7e54a..79706f9 100644 --- a/authzed/api/v1/watch_service.proto +++ b/authzed/api/v1/watch_service.proto @@ -3,6 +3,7 @@ package authzed.api.v1; 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"; @@ -29,11 +30,18 @@ message WatchRequest { // optional_relationship_filters cannot be used. repeated string optional_object_types = 1 [ (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 046a6f4..27b564a 100644 --- a/authzed/api/v1alpha1/schema.proto +++ b/authzed/api/v1alpha1/schema.proto @@ -1,6 +1,7 @@ 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"; @@ -28,10 +29,16 @@ message ReadSchemaRequest { // // 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 255944e..fe610fa 100644 --- a/authzed/api/v1alpha1/watchresources_service.proto +++ b/authzed/api/v1alpha1/watchresources_service.proto @@ -2,6 +2,7 @@ syntax = "proto3"; package authzed.api.v1alpha1; import "authzed/api/v1/core.proto"; +import "buf/validate/validate.proto"; import "google/api/annotations.proto"; import "validate/validate.proto"; @@ -26,17 +27,29 @@ service WatchResourcesService { 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. 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 d9c8dd9a620475b5684f669349544ca44bd3f7d1 Mon Sep 17 00:00:00 2001 From: Tanner Stirrat Date: Thu, 21 Nov 2024 14:05:05 -0700 Subject: [PATCH 4/6] 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 7beaa9f..885b1b0 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 b1e1ea7767a07832b09b63165825c499aa8f691e Mon Sep 17 00:00:00 2001 From: Tanner Stirrat Date: Thu, 21 Nov 2024 14:18:02 -0700 Subject: [PATCH 5/6] 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 885b1b0..a6d823d 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 5199e7b142c4c866bcd3edf6be6e10d3334f3e06 Mon Sep 17 00:00:00 2001 From: Tanner Stirrat Date: Fri, 22 Nov 2024 12:37:18 -0700 Subject: [PATCH 6/6] 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 a6d823d..066825c 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 }}"