syntax = "proto3"; package openfga.v1; import "google/api/field_behavior.proto"; import "protoc-gen-openapiv2/options/annotations.proto"; import "validate/validate.proto"; message AuthorizationModel { string id = 1 [ (google.api.field_behavior) = REQUIRED, (validate.rules).string = { pattern: "^[ABCDEFGHJKMNPQRSTVWXYZ0-9]{26}$", ignore_empty: false }, (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {example: "\"01G5JAVJ41T49E9TT3SKVS7X1J\""} ]; string schema_version = 2 [ (google.api.field_behavior) = REQUIRED, (validate.rules).string = { pattern: "^[1-9].[1-9]$", ignore_empty: false }, json_name = "schema_version" ]; repeated TypeDefinition type_definitions = 3 [ json_name = "type_definitions", (google.api.field_behavior) = REQUIRED, (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {example: "[{\"type\": \"user\"}, {\"type\":\"document\",\"relations\":{\"reader\":{\"union\":{\"child\":[{\"this\":{}},{\"computedUserset\":{\"object\":\"\",\"relation\":\"writer\"}}]}},\"writer\":{\"this\":{}}},\"metadata\":{\"relations\":{\"reader\":{\"directly_related_user_types\":[{\"type\":\"user\"}]},\"writer\":{\"directly_related_user_types\":[{\"type\":\"user\"}]}}}}]"} ]; map conditions = 4 [ json_name = "conditions", (validate.rules).map.max_pairs = 25, (validate.rules).map.keys.string = { pattern: "^[^:#@\\s]{1,50}$", ignore_empty: false } ]; } message TypeDefinition { string type = 1 [ (validate.rules).string = { pattern: "^[^:#@\\s]{1,254}$", ignore_empty: false }, (google.api.field_behavior) = REQUIRED, (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {example: "\"document\""} ]; map relations = 2 [ (validate.rules).map.keys.string = {pattern: "^[^:#@\\s]{1,50}$"}, (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {example: "{\"reader\":{\"union\":{\"child\":[{\"this\":{}},{\"computedUserset\":{\"object\":\"\",\"relation\":\"writer\"}}]}},\"writer\":{\"this\":{}}}"} ]; // A map whose keys are the name of the relation and whose value is the Metadata for that relation. // It also holds information around the module name and source file if this model was constructed // from a modular model. Metadata metadata = 3; } message Relation { string name = 1 [(validate.rules).string = { pattern: "^[^:#@\\s]{1,50}$", ignore_empty: false }]; Userset rewrite = 2 [ (validate.rules).message.required = true, (google.api.field_behavior) = REQUIRED ]; RelationTypeInfo type_info = 3; } message RelationTypeInfo { repeated RelationReference directly_related_user_types = 1 [json_name = "directly_related_user_types"]; } message Metadata { map relations = 1; string module = 2 [(validate.rules).string = { pattern: "^[^:#@\\s]{1,50}$", ignore_empty: true }]; SourceInfo source_info = 3 [json_name = "source_info"]; } message SourceInfo { string file = 1 [(validate.rules).string = { pattern: "^[a-zA-Z0-9_\\-\\/]{1,100}\\.fga$", ignore_empty: true }]; } message RelationMetadata { repeated RelationReference directly_related_user_types = 1 [json_name = "directly_related_user_types"]; string module = 2 [(validate.rules).string = { pattern: "^[^:#@\\s]{1,50}$", ignore_empty: true }]; SourceInfo source_info = 3 [json_name = "source_info"]; } // RelationReference represents a relation of a particular object type (e.g. 'document#viewer'). message RelationReference { string type = 1 [ (validate.rules).string = { pattern: "^[^:#@\\s]{1,254}$", ignore_empty: false }, (google.api.field_behavior) = REQUIRED, (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {example: "\"group\""} ]; oneof relation_or_wildcard { string relation = 2 [ (validate.rules).string = { pattern: "^[^:#@\\s]{1,50}$", ignore_empty: true }, (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {example: "\"member\""} ]; Wildcard wildcard = 3; } // The name of a condition that is enforced over the allowed relation. string condition = 4 [(validate.rules).string = { pattern: "^[^:#@\\s]{1,50}$", ignore_empty: true }]; } message Wildcard {} message Usersets { repeated Userset child = 1 [(google.api.field_behavior) = REQUIRED]; } message Difference { Userset base = 1 [ (validate.rules).message.required = true, (google.api.field_behavior) = REQUIRED ]; Userset subtract = 2 [ (validate.rules).message.required = true, (google.api.field_behavior) = REQUIRED ]; } message Userset { oneof userset { DirectUserset this = 1; ObjectRelation computed_userset = 2; TupleToUserset tuple_to_userset = 3; Usersets union = 4; Usersets intersection = 5; Difference difference = 6; } } // A DirectUserset is a sentinel message for referencing // the direct members specified by an object/relation mapping. message DirectUserset {} message ObjectRelation { string object = 1 [(validate.rules).string = {max_bytes: 256}]; string relation = 2 [(validate.rules).string = {max_bytes: 50}]; } message ComputedUserset { string relation = 1 [ (google.api.field_behavior) = REQUIRED, (validate.rules).string = { max_bytes: 50, ignore_empty: false } ]; } message TupleToUserset { // The target object/relation ObjectRelation tupleset = 1 [ (google.api.field_behavior) = REQUIRED, (validate.rules).message.required = true ]; ObjectRelation computed_userset = 2 [ (google.api.field_behavior) = REQUIRED, (validate.rules).message.required = true ]; } message Condition { // A unique name for the condition string name = 1 [ (google.api.field_behavior) = REQUIRED, (validate.rules).string = { pattern: "^[^:#@\\s]{1,50}$", ignore_empty: false } ]; // A Google CEL expression, expressed as a string. string expression = 2 [ (google.api.field_behavior) = REQUIRED, (validate.rules).string = { max_bytes: 512, ignore_empty: false } ]; // A map of parameter names to the parameter's defined type reference. map parameters = 3 [ (validate.rules).map.max_pairs = 25, (validate.rules).map.keys.string = {pattern: "^[^:#@\\s]{1,50}$"} ]; ConditionMetadata metadata = 4; } message ConditionMetadata { string module = 1 [(validate.rules).string = { pattern: "^[^:#@\\s]{1,50}$", ignore_empty: true }]; SourceInfo source_info = 2 [json_name = "source_info"]; } message ConditionParamTypeRef { enum TypeName { TYPE_NAME_UNSPECIFIED = 0; TYPE_NAME_ANY = 1; TYPE_NAME_BOOL = 2; TYPE_NAME_STRING = 3; TYPE_NAME_INT = 4; TYPE_NAME_UINT = 5; TYPE_NAME_DOUBLE = 6; TYPE_NAME_DURATION = 7; TYPE_NAME_TIMESTAMP = 8; TYPE_NAME_MAP = 9; TYPE_NAME_LIST = 10; TYPE_NAME_IPADDRESS = 11; } TypeName type_name = 1 [ json_name = "type_name", (google.api.field_behavior) = REQUIRED, (validate.rules).enum.defined_only = true ]; repeated ConditionParamTypeRef generic_types = 2 [ json_name = "generic_types", (validate.rules).repeated.max_items = 5 ]; }