Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Promote the reflection APIs into stable #129

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 8 additions & 12 deletions authzed/api/v1/experimental_service.proto
Original file line number Diff line number Diff line change
Expand Up @@ -55,48 +55,44 @@ service ExperimentalService {
option deprecated = true;
}

// EXPERIMENTAL: ReflectSchema is an API that allows clients to reflect the schema stored in
// SpiceDB. This is useful for clients that need to introspect the schema of a SpiceDB instance.
// DEPRECATED: Promoted to ReflectSchema in the stable API.
rpc ExperimentalReflectSchema(ExperimentalReflectSchemaRequest)
returns (ExperimentalReflectSchemaResponse) {
option (google.api.http) = {
post: "/v1/experimental/reflectschema"
body: "*"
};
option deprecated = true;
}

// 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`.
// DEPRECATED: Promoted to ComputablePermissions in the stable API.
rpc ExperimentalComputablePermissions(ExperimentalComputablePermissionsRequest)
returns (ExperimentalComputablePermissionsResponse) {
option (google.api.http) = {
post: "/v1/experimental/permissions/computable"
body: "*"
};
option deprecated = true;
}

// 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.
// DEPRECATED: Promoted to DependentRelations in the stable API.
rpc ExperimentalDependentRelations(ExperimentalDependentRelationsRequest)
returns (ExperimentalDependentRelationsResponse) {
option (google.api.http) = {
post: "/v1/experimental/permissions/dependent"
body: "*"
};
option deprecated = true;
}

// 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.
// DEPRECATED: Promoted to DiffSchema in the stable API.
rpc ExperimentalDiffSchema(ExperimentalDiffSchemaRequest)
returns (ExperimentalDiffSchemaResponse) {
option (google.api.http) = {
post: "/v1/experimental/diffschema"
body: "*"
};
option deprecated = true;
}

// EXPERIMENTAL: RegisterRelationshipCounter registers a new filter for counting relationships. A filter must be registered before
Expand Down
237 changes: 237 additions & 0 deletions authzed/api/v1/schema_service.proto
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import "google/api/annotations.proto";
import "validate/validate.proto";

import "authzed/api/v1/core.proto";
import "authzed/api/v1/permission_service.proto";

// SchemaService implements operations on a Permissions System's Schema.
service SchemaService {
Expand All @@ -31,6 +32,49 @@ service SchemaService {
body: "*"
};
}

// ReflectSchema reflects the current schema stored in SpiceDB, returning a structural
// form of the schema for use by client tooling.
rpc ReflectSchema(ReflectSchemaRequest)
returns (ReflectSchemaResponse) {
option (google.api.http) = {
post: "/v1/schema/reflectschema"
body: "*"
};
}

// ComputablePermissions returns the set of permissions that compute based off a relation
// in the current schema. For example, if the schema has a relation `viewer` and a permission
// `view` defined as `permission view = viewer + editor`, then the
// computable permissions for the relation `viewer` will include `view`.
rpc ComputablePermissions(ComputablePermissionsRequest)
returns (ComputablePermissionsResponse) {
option (google.api.http) = {
post: "/v1/schema/permissions/computable"
body: "*"
};
}

// DependentRelations returns the set of relations and permissions that used
// to compute a permission, recursively, in the current schema. It is the
// inverse of the ComputablePermissions API.
rpc DependentRelations(DependentRelationsRequest)
returns (DependentRelationsResponse) {
option (google.api.http) = {
post: "/v1/schema/permissions/dependent"
body: "*"
};
}

// DiffSchema returns the difference between the specified schema and the current
// schema stored in SpiceDB.
rpc DiffSchema(DiffSchemaRequest)
returns (DiffSchemaResponse) {
option (google.api.http) = {
post: "/v1/schema/diffschema"
body: "*"
};
}
}

// ReadSchemaRequest returns the schema from the database.
Expand Down Expand Up @@ -60,3 +104,196 @@ message WriteSchemaResponse {
// written_at is the ZedToken at which the schema was written.
ZedToken written_at = 1 [ (validate.rules).message.required = true ];
}

// Reflection types ////////////////////////////////////////////

message ReflectSchemaRequest {
Consistency consistency = 1;

// optional_filters defines optional filters that are applied in
// an OR fashion to the schema, before being returned
repeated ReflectionSchemaFilter optional_filters = 2;
}

message ReflectSchemaResponse {
// definitions are the definitions defined in the schema.
repeated ReflectionDefinition definitions = 1;

// caveats are the caveats defined in the schema.
repeated ReflectionCaveat caveats = 2;

// read_at is the ZedToken at which the schema was read.
ZedToken read_at = 3;
}

// ReflectionSchemaFilter is a filter that can be applied to the schema on reflection.
message ReflectionSchemaFilter {
// optional_definition_name_filter is a prefix that is matched against the definition name.
string optional_definition_name_filter = 1;

// optional_caveat_name_filter is a prefix that is matched against the caveat name.
string optional_caveat_name_filter = 2;

// optional_relation_name_filter is a prefix that is matched against the relation name.
string optional_relation_name_filter = 3;

// optional_permission_name_filter is a prefix that is matched against the permission name.
string optional_permission_name_filter = 4;
}

// ReflectionDefinition is the representation of a definition in the schema.
message ReflectionDefinition {
string name = 1;

// comment is a human-readable comments on the definition. Will include
// delimiter characters.
string comment = 2;

repeated ReflectionRelation relations = 3;
repeated ReflectionPermission permissions = 4;
}

// ReflectionCaveat is the representation of a caveat in the schema.
message ReflectionCaveat {
string name = 1;

// comment is a human-readable comments on the caveat. Will include
// delimiter characters.
string comment = 2;

repeated ReflectionCaveatParameter parameters = 3;
string expression = 4;
}

// ReflectionCaveatParameter is the representation of a parameter in a caveat.
message ReflectionCaveatParameter {
string name = 1;

// type is the type of the parameter. Will be a string representing the
// type, e.g. `int` or `list<string>`
string type = 2;
string parent_caveat_name = 3;
}

// ReflectionRelation is the representation of a relation in the schema.
message ReflectionRelation {
string name = 1;
string comment = 2;
string parent_definition_name = 3;
repeated ReflectionTypeReference subject_types = 4;
}

// ReflectionTypeReference is the representation of a type reference in the schema.
message ReflectionTypeReference {
// subject_definition_name is the name of the subject's definition.
string subject_definition_name = 1;

// optional_caveat_name is the name of the caveat that is applied to the subject, if any.
string optional_caveat_name = 2;

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;
}
}

// ReflectionPermission is the representation of a permission in the schema.
message ReflectionPermission {
string name = 1;

// comment is a human-readable comments on the permission. Will include
// delimiter characters.
string comment = 2;
string parent_definition_name = 3;
}

message ComputablePermissionsRequest {
Consistency consistency = 1;
string definition_name = 2;
string relation_name = 3;

// optional_definition_name_match is a prefix that is matched against the definition name(s)
// for the permissions returned.
// If not specified, will be ignored.
string optional_definition_name_filter = 4;
}

// ReflectionRelationReference is a reference to a relation or permission in the schema.
message ReflectionRelationReference {
string definition_name = 1;
string relation_name = 2;
bool is_permission = 3;
}

message ComputablePermissionsResponse {
repeated ReflectionRelationReference permissions = 1;

// read_at is the ZedToken at which the schema was read.
ZedToken read_at = 2;
}

message DependentRelationsRequest {
Consistency consistency = 1;
string definition_name = 2;
string permission_name = 3;
}

message DependentRelationsResponse {
repeated ReflectionRelationReference relations = 1;

// read_at is the ZedToken at which the schema was read.
ZedToken read_at = 2;
}

message DiffSchemaRequest {
Consistency consistency = 1;
string comparison_schema = 2;
}

message DiffSchemaResponse {
repeated ReflectionSchemaDiff diffs = 1;

// read_at is the ZedToken at which the schema was read.
ZedToken read_at = 2;
}

message ReflectionRelationSubjectTypeChange {
ReflectionRelation relation = 1;
ReflectionTypeReference changed_subject_type = 2;
}

message ReflectionCaveatParameterTypeChange {
ReflectionCaveatParameter parameter = 1;
string previous_type = 2;
}

// ReflectionSchemaDiff is the representation of a diff between two schemas.
message ReflectionSchemaDiff {
oneof diff {
ReflectionDefinition definition_added = 1;
ReflectionDefinition definition_removed = 2;
ReflectionDefinition definition_doc_comment_changed = 3;
ReflectionRelation relation_added = 4;
ReflectionRelation relation_removed = 5;
ReflectionRelation relation_doc_comment_changed = 6;
ReflectionRelationSubjectTypeChange relation_subject_type_added = 7;
ReflectionRelationSubjectTypeChange relation_subject_type_removed = 8;
ReflectionPermission permission_added = 9;
ReflectionPermission permission_removed = 10;
ReflectionPermission permission_doc_comment_changed = 11;
ReflectionPermission permission_expr_changed = 12;
ReflectionCaveat caveat_added = 13;
ReflectionCaveat caveat_removed = 14;
ReflectionCaveat caveat_doc_comment_changed = 15;
ReflectionCaveat caveat_expr_changed = 16;
ReflectionCaveatParameter caveat_parameter_added = 17;
ReflectionCaveatParameter caveat_parameter_removed = 18;
ReflectionCaveatParameterTypeChange caveat_parameter_type_changed = 19;
}
}
Loading