From 7c08e107683e6f840e5709f4a18aa7e002a3a2fd Mon Sep 17 00:00:00 2001 From: Drew McLean Date: Thu, 2 Apr 2026 13:10:09 -0400 Subject: [PATCH 1/2] [CLDIAM-651] Add custom roles --- .../cloudservice/v1/request_response.proto | 86 +++++++++++++++++- .../api/cloud/cloudservice/v1/service.proto | 88 +++++++++++++++++++ temporal/api/cloud/identity/v1/message.proto | 55 ++++++++++++ 3 files changed, 228 insertions(+), 1 deletion(-) diff --git a/temporal/api/cloud/cloudservice/v1/request_response.proto b/temporal/api/cloud/cloudservice/v1/request_response.proto index e9815da..3249bc6 100644 --- a/temporal/api/cloud/cloudservice/v1/request_response.proto +++ b/temporal/api/cloud/cloudservice/v1/request_response.proto @@ -1093,4 +1093,88 @@ message GetBillingReportRequest { message GetBillingReportResponse { // The billing report retrieved. temporal.api.cloud.billing.v1.BillingReport billing_report = 1; -} \ No newline at end of file +} + +// temporal:versioning:min_version=v0.13.0 +message GetCustomRolesRequest { + // The requested size of the page to retrieve. + // Cannot exceed 1000. Defaults to 100. + int32 page_size = 1; + // The page token if this is continuing from another response. + string page_token = 2; +} + +// temporal:versioning:min_version=v0.13.0 +message GetCustomRolesResponse { + // The list of custom roles in ascending ID order. + repeated temporal.api.cloud.identity.v1.CustomRole custom_roles = 1; + // The next page token. + string next_page_token = 2; +} + +// temporal:versioning:min_version=v0.13.0 +message GetCustomRoleRequest { + // The ID of the custom role to retrieve. + string role_id = 1; +} + +// temporal:versioning:min_version=v0.13.0 +message GetCustomRoleResponse { + // The custom role retrieved. + temporal.api.cloud.identity.v1.CustomRole custom_role = 1; +} + +// temporal:versioning:min_version=v0.13.0 +message CreateCustomRoleRequest { + // The specification for the custom role to create. + temporal.api.cloud.identity.v1.CustomRoleSpec spec = 1; + // The ID to use for this async operation. + // Optional, if not provided a random ID will be generated. + string async_operation_id = 2; +} + +// temporal:versioning:min_version=v0.13.0 +message CreateCustomRoleResponse { + // The ID of the custom role created. + string role_id = 1; + // The async operation. + temporal.api.cloud.operation.v1.AsyncOperation async_operation = 2; +} + +// temporal:versioning:min_version=v0.13.0 +message UpdateCustomRoleRequest { + // The ID of the custom role to update. + string role_id = 1; + // The new custom role specification. + temporal.api.cloud.identity.v1.CustomRoleSpec spec = 2; + // The version of the custom role for which this update is intended. + // The latest version can be found in the GetCustomRole operation response. + string resource_version = 3; + // The ID to use for this async operation. + // Optional, if not provided a random ID will be generated. + string async_operation_id = 4; +} + +// temporal:versioning:min_version=v0.13.0 +message UpdateCustomRoleResponse { + // The async operation. + temporal.api.cloud.operation.v1.AsyncOperation async_operation = 1; +} + +// temporal:versioning:min_version=v0.13.0 +message DeleteCustomRoleRequest { + // The ID of the custom role to delete. + string role_id = 1; + // The version of the custom role for which this delete is intended. + // The latest version can be found in the GetCustomRole operation response. + string resource_version = 2; + // The ID to use for this async operation. + // Optional, if not provided a random ID will be generated. + string async_operation_id = 3; +} + +// temporal:versioning:min_version=v0.13.0 +message DeleteCustomRoleResponse { + // The async operation. + temporal.api.cloud.operation.v1.AsyncOperation async_operation = 1; +} diff --git a/temporal/api/cloud/cloudservice/v1/service.proto b/temporal/api/cloud/cloudservice/v1/service.proto index 302da96..a6c764c 100644 --- a/temporal/api/cloud/cloudservice/v1/service.proto +++ b/temporal/api/cloud/cloudservice/v1/service.proto @@ -48,6 +48,7 @@ option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_swagger) = { {name: "Connectivity Rules"; description: "Manage network connectivity rules"}, {name: "Regions"; description: "Query available regions"}, {name: "Account"; description: "Manage account settings and usage"}, + {name: "Custom Roles"; description: "Manage custom roles and their permissions"}, {name: "Operations"; description: "Query async operation status"} ]; }; @@ -1157,4 +1158,91 @@ service CloudService { }; }; } + + // Get custom roles + // temporal:versioning:min_version=v0.13.0 + rpc GetCustomRoles(GetCustomRolesRequest) returns (GetCustomRolesResponse) { + option (google.api.http) = { + get: "/cloud/custom-roles" + }; + option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = { + tags: ["Custom Roles"]; + summary: "List custom roles"; + description: "Returns a list of custom roles in the account"; + external_docs: { + url: "https://docs.temporal.io/cloud/custom-roles"; + description: "Custom roles documentation"; + }; + }; + } + + // Get a custom role + // temporal:versioning:min_version=v0.13.0 + rpc GetCustomRole(GetCustomRoleRequest) returns (GetCustomRoleResponse) { + option (google.api.http) = { + get: "/cloud/custom-roles/{role_id}" + }; + option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = { + tags: ["Custom Roles"]; + summary: "Get custom role by ID"; + description: "Returns details for a specific custom role"; + external_docs: { + url: "https://docs.temporal.io/cloud/custom-roles"; + description: "Custom roles documentation"; + }; + }; + } + + // Create a custom role + // temporal:versioning:min_version=v0.13.0 + rpc CreateCustomRole(CreateCustomRoleRequest) returns (CreateCustomRoleResponse) { + option (google.api.http) = { + post: "/cloud/custom-roles" + body: "*" + }; + option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = { + tags: ["Custom Roles"]; + summary: "Create a custom role"; + description: "Creates a new custom role in the account"; + external_docs: { + url: "https://docs.temporal.io/cloud/custom-roles"; + description: "Custom roles documentation"; + }; + }; + } + + // Update a custom role + // temporal:versioning:min_version=v0.13.0 + rpc UpdateCustomRole(UpdateCustomRoleRequest) returns (UpdateCustomRoleResponse) { + option (google.api.http) = { + post: "/cloud/custom-roles/{role_id}" + body: "*" + }; + option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = { + tags: ["Custom Roles"]; + summary: "Update a custom role"; + description: "Updates an existing custom role"; + external_docs: { + url: "https://docs.temporal.io/cloud/custom-roles"; + description: "Custom roles documentation"; + }; + }; + } + + // Delete a custom role + // temporal:versioning:min_version=v0.13.0 + rpc DeleteCustomRole(DeleteCustomRoleRequest) returns (DeleteCustomRoleResponse) { + option (google.api.http) = { + delete: "/cloud/custom-roles/{role_id}" + }; + option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = { + tags: ["Custom Roles"]; + summary: "Delete a custom role"; + description: "Deletes a custom role from the account"; + external_docs: { + url: "https://docs.temporal.io/cloud/custom-roles"; + description: "Custom roles documentation"; + }; + }; + } } diff --git a/temporal/api/cloud/identity/v1/message.proto b/temporal/api/cloud/identity/v1/message.proto index 5d79ddf..3b304da 100644 --- a/temporal/api/cloud/identity/v1/message.proto +++ b/temporal/api/cloud/identity/v1/message.proto @@ -37,6 +37,10 @@ message AccountAccess { ROLE_READ = 5; // Gives read only access to the account. ROLE_METRICS_READ = 6; // Gives read only access to the account metrics. } + + // List of custom role IDs assigned to the user or service account. + // temporal:versioning:min_version=v0.13.0 + repeated string custom_roles = 3; } message NamespaceAccess { @@ -73,6 +77,10 @@ message Access { // The map of namespace accesses // The key is the namespace name and the value is the access to the namespace map namespace_accesses = 2; + // List of custom role IDs assigned to the user or service account. + // Deprecated: Not supported after v0.12.0 api version. Use account_access.custom_roles instead. + // temporal:versioning:max_version=v0.12.0 + repeated string custom_roles_deprecated = 4 [deprecated = true]; } message NamespaceScopedAccess { @@ -294,3 +302,50 @@ message ApiKeySpec { // True if the API key is disabled. bool disabled = 6; } + +// temporal:versioning:min_version=v0.13.0 +message CustomRoleSpec { + // The name of the custom role. + string name = 1; + // The description of the custom role. + string description = 2; + // The permissions assigned to the custom role. + repeated Permission permissions = 3; + + message Resources { + // The resource type the permission applies to. + string resource_type = 1; + // The resource IDs the permission applies to. Can be empty if allow_all is true. + repeated string resource_ids = 2; + // Whether the permission applies to all resources of the given type. + bool allow_all = 3; + } + + message Permission { + // The resources the permission applies to. + Resources resources = 1; + // The actions allowed by the permission. + repeated string actions = 2; + } +} + +// temporal:versioning:min_version=v0.13.0 +message CustomRole { + // The id of the custom role. + string id = 1; + // The current version of the custom role specification. + // The next update operation will have to include this version. + string resource_version = 2; + // The custom role specification. + CustomRoleSpec spec = 3; + // The current state of the custom role. + // For any failed state, reach out to Temporal Cloud support for remediation. + temporal.api.cloud.resource.v1.ResourceState state = 4; + // The id of the async operation that is creating/updating/deleting the custom role, if any. + string async_operation_id = 5; + // The date and time when the custom role was created. + google.protobuf.Timestamp created_time = 6; + // The date and time when the custom role was last modified. + // Will not be set if the custom role has never been modified. + google.protobuf.Timestamp last_modified_time = 7; +} From 54274d7a6faaa3f87d5ad2f0c3261fb332824b1f Mon Sep 17 00:00:00 2001 From: Drew McLean Date: Thu, 9 Apr 2026 11:36:48 -0400 Subject: [PATCH 2/2] Downgrade all references from v0.14.0 to v0.13.0 --- README.md | 2 +- VERSION | 2 +- temporal/api/cloud/namespace/v1/message.proto | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index eabe4cf..e58b236 100644 --- a/README.md +++ b/README.md @@ -15,7 +15,7 @@ To use the Cloud Ops API in your project, preform the following 4 steps: The client is expected to pass in a `temporal-cloud-api-version` header with the api version identifier with every request it makes to the apis. The backend will use the version to safely mutate resources. The `temporal:versioning:min_version` label specifies the minimum version of the API that supports the field. -Current Version `v0.14.0` +Current Version `v0.13.0` ### URL diff --git a/VERSION b/VERSION index 4a29f93..6345c21 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -v0.14.0 +v0.13.0 diff --git a/temporal/api/cloud/namespace/v1/message.proto b/temporal/api/cloud/namespace/v1/message.proto index a141325..a769202 100644 --- a/temporal/api/cloud/namespace/v1/message.proto +++ b/temporal/api/cloud/namespace/v1/message.proto @@ -91,7 +91,7 @@ message HighAvailabilitySpec { bool disable_managed_failover = 1; // Flag to disable passive poller forwarding for this namespace. - // temporal:versioning:min_version=v0.14.0 + // temporal:versioning:min_version=v0.13.0 bool disable_passive_poller_forwarding = 2; }