Update vendored @remoteapis for PR bazelbuild/remote-apis#112

Closes #10818.

Signed-off-by: Philipp Wollermann <philwo@google.com>
diff --git a/third_party/remoteapis/BUILD.bazel b/third_party/remoteapis/BUILD.bazel
index 37d9d00..bffb738c 100644
--- a/third_party/remoteapis/BUILD.bazel
+++ b/third_party/remoteapis/BUILD.bazel
@@ -18,6 +18,7 @@
 
 JAVA_LIBRARY_PROTOS = [
     "build_bazel_semver_semver",
+    "build_bazel_remote_asset_v1_remote_asset",
     "build_bazel_remote_execution_v2_remote_execution",
 ]
 
@@ -30,12 +31,25 @@
 filegroup(
     name = "dist_jars",
     srcs = [":" + proto + "_java_proto_srcs" for proto in JAVA_LIBRARY_PROTOS] + [
+        ":build_bazel_remote_asset_v1_remote_asset_java_grpc_srcs",
         ":build_bazel_remote_execution_v2_remote_execution_java_grpc_srcs",
     ],
     visibility = ["@//src:__pkg__"],
 )
 
 proto_library(
+    name = "build_bazel_remote_asset_v1_remote_asset_proto",
+    srcs = ["build/bazel/remote/asset/v1/remote_asset.proto"],
+    deps = [
+        ":build_bazel_remote_execution_v2_remote_execution_proto",
+        "@com_google_protobuf//:duration_proto",
+        "@com_google_protobuf//:timestamp_proto",
+        "@googleapis//:google_api_annotations_proto",
+        "@googleapis//:google_rpc_status_proto",
+    ],
+)
+
+proto_library(
     name = "build_bazel_remote_execution_v2_remote_execution_proto",
     srcs = ["build/bazel/remote/execution/v2/remote_execution.proto"],
     deps = [
@@ -55,6 +69,11 @@
 )
 
 java_proto_library(
+    name = "build_bazel_remote_asset_v1_remote_asset_java_proto",
+    deps = [":build_bazel_remote_asset_v1_remote_asset_proto"],
+)
+
+java_proto_library(
     name = "build_bazel_remote_execution_v2_remote_execution_java_proto",
     deps = [":build_bazel_remote_execution_v2_remote_execution_proto"],
 )
@@ -65,6 +84,12 @@
 )
 
 java_grpc_library(
+    name = "build_bazel_remote_asset_v1_remote_asset_java_grpc",
+    srcs = [":build_bazel_remote_asset_v1_remote_asset_proto"],
+    deps = [":build_bazel_remote_asset_v1_remote_asset_java_proto"],
+)
+
+java_grpc_library(
     name = "build_bazel_remote_execution_v2_remote_execution_java_grpc",
     srcs = [":build_bazel_remote_execution_v2_remote_execution_proto"],
     deps = [
diff --git a/third_party/remoteapis/build/bazel/remote/asset/v1/remote_asset.proto b/third_party/remoteapis/build/bazel/remote/asset/v1/remote_asset.proto
new file mode 100644
index 0000000..52a01e5
--- /dev/null
+++ b/third_party/remoteapis/build/bazel/remote/asset/v1/remote_asset.proto
@@ -0,0 +1,445 @@
+// Copyright 2020 The Bazel Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+syntax = "proto3";
+
+package build.bazel.remote.asset.v1;
+
+import "build/bazel/remote/execution/v2/remote_execution.proto";
+import "google/api/annotations.proto";
+import "google/protobuf/duration.proto";
+import "google/protobuf/timestamp.proto";
+import "google/rpc/status.proto";
+
+option csharp_namespace = "Build.Bazel.Remote.Asset.v1";
+option go_package = "remoteasset";
+option java_multiple_files = true;
+option java_outer_classname = "RemoteAssetProto";
+option java_package = "build.bazel.remote.asset.v1";
+option objc_class_prefix = "RA";
+
+// The Remote Asset API provides a mapping from a URI and Qualifiers to
+// Digests.
+//
+// Multiple URIs may be used to refer to the same content.  For example, the
+// same tarball may exist at multiple mirrors and thus be retrievable from
+// multiple URLs.  When URLs are used, these should refer to actual content as
+// Fetch service implementations may choose to fetch the content directly
+// from the origin.  For example, the HEAD of a git repository's active branch
+// can be referred to as:
+//
+//     uri: https://github.com/bazelbuild/remote-apis.git
+//
+// URNs may be used to strongly identify content, for instance by using the
+// uuid namespace identifier: urn:uuid:f81d4fae-7dec-11d0-a765-00a0c91e6bf6.
+// This is most applicable to named content that is Push'd, where the URN
+// serves as an agreed-upon key, but carries no other inherent meaning.
+//
+// Service implementations may choose to support only URLs, only URNs for
+// Push'd content, only other URIs for which the server and client agree upon
+// semantics of, or any mixture of the above.
+
+// Qualifiers are used to disambiguate or sub-select content that shares a URI.
+// This may include specifying a particular commit or branch, in the case of
+// URIs referencing a repository; they could also be used to specify a
+// particular subdirectory of a repository or tarball. Qualifiers may also be
+// used to ensure content matches what the client expects, even when there is
+// no ambiguity to be had - for example, a qualifier specifying a checksum
+// value.
+//
+// In cases where the semantics of the request are not immediately clear from
+// the URL and/or qualifiers - e.g. dictated by URL scheme - it is recommended
+// to use an additional qualifier to remove the ambiguity. The `resource_type`
+// qualifier is recommended for this purpose.
+//
+// Qualifiers may be supplied in any order.
+message Qualifier {
+  // The "name" of the qualifier, for example "resource_type".
+  // No separation is made between 'standard' and 'nonstandard'
+  // qualifiers, in accordance with https://tools.ietf.org/html/rfc6648,
+  // however implementers *SHOULD* take care to avoid ambiguity.
+  string name = 1;
+
+  // The "value" of the qualifier. Semantics will be dictated by the name.
+  string value = 2;
+}
+
+// The Fetch service resolves or fetches assets referenced by URI and
+// Qualifiers, returning a Digest for the content in
+// [ContentAddressableStorage][build.bazel.remote.execution.v2.ContentAddressableStorage].
+//
+// As with other services in the Remote Execution API, any call may return an
+// error with a [RetryInfo][google.rpc.RetryInfo] error detail providing
+// information about when the client should retry the request; clients SHOULD
+// respect the information provided.
+service Fetch {
+  // Resolve or fetch referenced assets, making them available to the caller and
+  // other consumers in the [ContentAddressableStorage][build.bazel.remote.execution.v2.ContentAddressableStorage].
+  //
+  // Servers *MAY* fetch content that they do not already have cached, for any
+  // URLs they support.
+  //
+  // Servers *SHOULD* ensure that referenced files are present in the CAS at the
+  // time of the response, and (if supported) that they will remain available
+  // for a reasonable period of time. The TTLs of the referenced blobs *SHOULD*
+  // be increased if necessary and applicable.
+  // In the event that a client receives a reference to content that is no
+  // longer present, it *MAY* re-issue the request with
+  // `oldest_content_accepted` set to a more recent timestamp than the original
+  // attempt, to induce a re-fetch from origin.
+  //
+  // Servers *MAY* cache fetched content and reuse it for subsequent requests,
+  // subject to `oldest_content_accepted`.
+  //
+  // Servers *MAY* support the complementary [Push][build.bazel.remote.asset.v1.Push]
+  // API and allow content to be directly inserted for use in future fetch
+  // responses.
+  //
+  // Servers *MUST* ensure Fetch'd content matches all the specified
+  // qualifiers except in the case of previously Push'd resources, for which
+  // the server *MAY* trust the pushing client to have set the qualifiers
+  // correctly, without validation.
+  //
+  // Servers not implementing the complementary [Push][build.bazel.remote.asset.v1.Push]
+  // API *MUST* reject requests containing qualifiers it does not support.
+  //
+  // Servers **MAY** transform assets as part of the fetch. For example a
+  // tarball fetched by [FetchDirectory][build.bazel.remote.asset.v1.Fetch.FetchDirectory]
+  // might be unpacked, or a Git repository
+  // fetched by [FetchBlob][build.bazel.remote.asset.v1.Fetch.FetchBlob]
+  // might be passed through `git-archive`.
+  //
+  // Errors handling the requested assets will be returned as gRPC Status errors
+  // here; errors outside the server's control will be returned inline in the
+  // `status` field of the response (see comment there for details).
+  // The possible RPC errors include:
+  // * `INVALID_ARGUMENT`: One or more arguments were invalid, such as a
+  //   qualifier that is not supported by the server.
+  // * `RESOURCE_EXHAUSTED`: There is insufficient quota of some resource to
+  //   perform the requested operation. The client may retry after a delay.
+  // * `UNAVAILABLE`: Due to a transient condition the operation could not be
+  //   completed. The client should retry.
+  // * `INTERNAL`: An internal error occurred while performing the operation.
+  //   The client should retry.
+  // * `DEADLINE_EXCEEDED`: The fetch could not be completed within the given
+  //   RPC deadline. The client should retry for at least as long as the value
+  //   provided in `timeout` field of the request.
+  //
+  // In the case of unsupported qualifiers, the server *SHOULD* additionally
+  // send a [BadRequest][google.rpc.BadRequest] error detail where, for each
+  // unsupported qualifier, there is a `FieldViolation` with a `field` of
+  // `qualifiers.name` and a `description` of `"{qualifier}" not supported`
+  // indicating the name of the unsupported qualifier.
+  rpc FetchBlob(FetchBlobRequest) returns (FetchBlobResponse) {
+    option (google.api.http) = { post: "/v1/{instance_name=**}/assets:fetchBlob" body: "*" };
+  }
+  rpc FetchDirectory(FetchDirectoryRequest) returns (FetchDirectoryResponse) {
+    option (google.api.http) = { post: "/v1/{instance_name=**}/assets:fetchDirectory" body: "*" };
+  }
+}
+
+// A request message for
+// [Fetch.FetchBlob][build.bazel.remote.asset.v1.Fetch.FetchBlob].
+message FetchBlobRequest {
+  // The instance of the execution system to operate against. A server may
+  // support multiple instances of the execution system (with their own workers,
+  // storage, caches, etc.). The server MAY require use of this field to select
+  // between them in an implementation-defined fashion, otherwise it can be
+  // omitted.
+  string instance_name = 1;
+
+  // The timeout for the underlying fetch, if content needs to be retrieved from
+  // origin.
+  //
+  // If unset, the server *MAY* apply an implementation-defined timeout.
+  //
+  // If set, and the user-provided timeout exceeds the RPC deadline, the server
+  // *SHOULD* keep the fetch going after the RPC completes, to be made
+  // available for future Fetch calls. The server may also enforce (via clamping
+  // and/or an INVALID_ARGUMENT error) implementation-defined minimum and
+  // maximum timeout values.
+  //
+  // If this timeout is exceeded on an attempt to retrieve content from origin
+  // the client will receive DEADLINE_EXCEEDED in [FetchBlobResponse.status].
+  google.protobuf.Duration timeout = 2;
+
+  // The oldest content the client is willing to accept, as measured from the
+  // time it was Push'd or when the underlying retrieval from origin was 
+  // started.
+  // Upon retries of Fetch requests that cannot be completed within a single
+  // RPC, clients *SHOULD* provide the same value for subsequent requests as the
+  // original, to simplify combining the request with the previous attempt.
+  //
+  // If unset, the client *SHOULD* accept content of any age.
+  google.protobuf.Timestamp oldest_content_accepted = 3;
+
+  // The URI(s) of the content to fetch. These may be resources that the server
+  // can directly fetch from origin, in which case multiple URIs *SHOULD*
+  // represent the same content available at different locations (such as an
+  // origin and secondary mirrors). These may also be URIs for content known to
+  // the server through other mechanisms, e.g. pushed via the [Push][build.bazel.remote.asset.v1.Push]
+  // service.
+  //
+  // Clients *MUST* supply at least one URI. Servers *MAY* match any one of the
+  // supplied URIs.
+  repeated string uris = 4;
+
+  // Qualifiers sub-specifying the content to fetch - see comments on
+  // [Qualifier][build.bazel.remote.asset.v1.Qualifier].
+  // The same qualifiers apply to all URIs.
+  //
+  // Specified qualifier names *MUST* be unique.
+  repeated Qualifier qualifiers = 5;
+}
+
+// A response message for
+// [Fetch.FetchBlob][build.bazel.remote.asset.v1.Fetch.FetchBlob].
+message FetchBlobResponse {
+  // If the status has a code other than `OK`, it indicates that the operation
+  // was unable to be completed for reasons outside the servers' control.
+  // The possible fetch errors include:
+  // * `DEADLINE_EXCEEDED`: The operation could not be completed within the
+  //   specified timeout.
+  // * `NOT_FOUND`: The requested asset was not found at the specified location.
+  // * `PERMISSION_DENIED`: The request was rejected by a remote server, or
+  //   requested an asset from a disallowed origin.
+  // * `ABORTED`: The operation could not be completed, typically due to a
+  //   failed consistency check.
+  google.rpc.Status status = 1;
+
+  // The uri from the request that resulted in a successful retrieval, or from
+  // which the error indicated in `status` was obtained.
+  string uri = 2;
+
+  // Any qualifiers known to the server and of interest to clients.
+  repeated Qualifier qualifiers = 3;
+
+  // A minimum timestamp the content is expected to be available through.
+  // Servers *MAY* omit this field, if not known with confidence.
+  google.protobuf.Timestamp expires_at = 4;
+
+  // The result of the fetch, if the status had code `OK`.
+  // The digest of the file's contents, available for download through the CAS.
+  build.bazel.remote.execution.v2.Digest blob_digest = 5;
+}
+
+// A request message for
+// [Fetch.FetchDirectory][build.bazel.remote.asset.v1.Fetch.FetchDirectory].
+message FetchDirectoryRequest {
+  // The instance of the execution system to operate against. A server may
+  // support multiple instances of the execution system (with their own workers,
+  // storage, caches, etc.). The server MAY require use of this field to select
+  // between them in an implementation-defined fashion, otherwise it can be
+  // omitted.
+  string instance_name = 1;
+
+  // The timeout for the underlying fetch, if content needs to be retrieved from
+  // origin. This value is allowed to exceed the RPC deadline, in which case the
+  // server *SHOULD* keep the fetch going after the RPC completes, to be made
+  // available for future Fetch calls.
+  //
+  // If this timeout is exceeded on an attempt to retrieve content from origin
+  // the client will receive DEADLINE_EXCEEDED in [FetchDirectoryResponse.status].
+  google.protobuf.Duration timeout = 2;
+
+  // The oldest content the client is willing to accept, as measured from the
+  // time it was Push'd or when the underlying retrieval from origin was
+  // started.
+  // Upon retries of Fetch requests that cannot be completed within a single
+  // RPC, clients *SHOULD* provide the same value for subsequent requests as the
+  // original, to simplify combining the request with the previous attempt.
+  //
+  // If unset, the client *SHOULD* accept content of any age.
+  google.protobuf.Timestamp oldest_content_accepted = 3;
+
+  // The URI(s) of the content to fetch. These may be resources that the server
+  // can directly fetch from origin, in which case multiple URIs *SHOULD*
+  // represent the same content available at different locations (such as an
+  // origin and secondary mirrors). These may also be URIs for content known to
+  // the server through other mechanisms, e.g. pushed via the [Push][build.bazel.remote.asset.v1.Push]
+  // service.
+  //
+  // Clients *MUST* supply at least one URI. Servers *MAY* match any one of the
+  // supplied URIs.
+  repeated string uris = 4;
+
+  // Qualifiers sub-specifying the content to fetch - see comments on
+  // [Qualifier][build.bazel.remote.asset.v1.Qualifier].
+  // The same qualifiers apply to all URIs.
+  //
+  // Specified qualifier names *MUST* be unique.
+  repeated Qualifier qualifiers = 5;
+}
+
+// A response message for
+// [Fetch.FetchDirectory][build.bazel.remote.asset.v1.Fetch.FetchDirectory].
+message FetchDirectoryResponse {
+  // If the status has a code other than `OK`, it indicates that the operation
+  // was unable to be completed for reasons outside the servers' control.
+  // The possible fetch errors include:
+  // * `DEADLINE_EXCEEDED`: The operation could not be completed within the
+  //   specified timeout.
+  // * `NOT_FOUND`: The requested asset was not found at the specified location.
+  // * `PERMISSION_DENIED`: The request was rejected by a remote server, or
+  //   requested an asset from a disallowed origin.
+  // * `ABORTED`: The operation could not be completed, typically due to a
+  //   failed consistency check.
+  google.rpc.Status status = 1;
+
+  // The uri from the request that resulted in a successful retrieval, or from
+  // which the error indicated in `status` was obtained.
+  string uri = 2;
+
+  // Any qualifiers known to the server and of interest to clients.
+  repeated Qualifier qualifiers = 3;
+
+  // A minimum timestamp the content is expected to be available through.
+  // Servers *MAY* omit this field, if not known with confidence.
+  google.protobuf.Timestamp expires_at = 4;
+
+  // The result of the fetch, if the status had code `OK`.
+  // the root digest of a directory tree, suitable for fetching via
+  // [ContentAddressableStorage.GetTree].
+  build.bazel.remote.execution.v2.Digest root_directory_digest = 5;
+}
+
+// The Push service is complementary to the Fetch, and allows for
+// associating contents of URLs to be returned in future Fetch API calls.
+//
+// As with other services in the Remote Execution API, any call may return an
+// error with a [RetryInfo][google.rpc.RetryInfo] error detail providing
+// information about when the client should retry the request; clients SHOULD
+// respect the information provided.
+service Push {
+  // These APIs associate the identifying information of a resource, as
+  // indicated by URI and optionally Qualifiers, with content available in the
+  // CAS. For example, associating a repository url and a commit id with a
+  // Directory Digest.
+  //
+  // Servers *SHOULD* only allow trusted clients to associate content, and *MAY*
+  // only allow certain URIs to be pushed.
+  //
+  // Clients *MUST* ensure associated content is available in CAS prior to
+  // pushing.
+  //
+  // Clients *MUST* ensure the Qualifiers listed correctly match the contents,
+  // and Servers *MAY* trust these values without validation.
+  // Fetch servers *MAY* require exact match of all qualifiers when returning
+  // content previously pushed, or allow fetching content with only a subset of
+  // the qualifiers specified on Push.
+  //
+  // Clients can specify expiration information that the server *SHOULD*
+  // respect. Subsequent requests can be used to alter the expiration time.
+  //
+  // A minimal compliant Fetch implementation may support only Push'd content
+  // and return `NOT_FOUND` for any resource that was not pushed first.
+  // Alternatively, a compliant implementation may choose to not support Push
+  // and only return resources that can be Fetch'd from origin.
+  //
+  // Errors will be returned as gRPC Status errors.
+  // The possible RPC errors include:
+  // * `INVALID_ARGUMENT`: One or more arguments to the RPC were invalid.
+  // * `RESOURCE_EXHAUSTED`: There is insufficient quota of some resource to
+  //   perform the requested operation. The client may retry after a delay.
+  // * `UNAVAILABLE`: Due to a transient condition the operation could not be
+  //   completed. The client should retry.
+  // * `INTERNAL`: An internal error occurred while performing the operation.
+  //   The client should retry.
+  rpc PushBlob(PushBlobRequest) returns (PushBlobResponse) {
+    option (google.api.http) = { post: "/v1/{instance_name=**}/assets:pushBlob" body: "*" };
+  }
+
+  rpc PushDirectory(PushDirectoryRequest) returns (PushDirectoryResponse) {
+    option (google.api.http) = { post: "/v1/{instance_name=**}/assets:pushDirectory" body: "*" };
+  }
+}
+
+// A request message for
+// [Push.PushBlob][build.bazel.remote.asset.v1.Push.PushBlob].
+message PushBlobRequest {
+  // The instance of the execution system to operate against. A server may
+  // support multiple instances of the execution system (with their own workers,
+  // storage, caches, etc.). The server MAY require use of this field to select
+  // between them in an implementation-defined fashion, otherwise it can be
+  // omitted.
+  string instance_name = 1;
+
+  // The URI(s) of the content to associate. If multiple URIs are specified, the
+  // pushed content will be available to fetch by specifying any of them.
+  repeated string uris = 2;
+
+  // Qualifiers sub-specifying the content that is being pushed - see comments
+  // on [Qualifier][build.bazel.remote.asset.v1.Qualifier].
+  // The same qualifiers apply to all URIs.
+  repeated Qualifier qualifiers = 3;
+
+  // A time after which this content should stop being returned via [FetchBlob][build.bazel.remote.asset.v1.Fetch.FetchBlob].
+  // Servers *MAY* expire content early, e.g. due to storage pressure.
+  google.protobuf.Timestamp expire_at = 4;
+
+  // The blob to associate.
+  build.bazel.remote.execution.v2.Digest blob_digest = 5;
+
+  // Referenced blobs or directories that need to not expire before expiration
+  // of this association, in addition to `blob_digest` itself.
+  // These fields are hints - clients *MAY* omit them, and servers *SHOULD*
+  // respect them, at the risk of increased incidents of Fetch responses
+  // indirectly referencing unavailable blobs.
+  repeated build.bazel.remote.execution.v2.Digest references_blobs = 6;
+  repeated build.bazel.remote.execution.v2.Digest references_directories = 7;
+}
+
+// A response message for
+// [Push.PushBlob][build.bazel.remote.asset.v1.Push.PushBlob].
+message PushBlobResponse { /* empty */ }
+
+// A request message for
+// [Push.PushDirectory][build.bazel.remote.asset.v1.Push.PushDirectory].
+message PushDirectoryRequest {
+  // The instance of the execution system to operate against. A server may
+  // support multiple instances of the execution system (with their own workers,
+  // storage, caches, etc.). The server MAY require use of this field to select
+  // between them in an implementation-defined fashion, otherwise it can be
+  // omitted.
+  string instance_name = 1;
+
+  // The URI(s) of the content to associate. If multiple URIs are specified, the
+  // pushed content will be available to fetch by specifying any of them.
+  repeated string uris = 2;
+
+  // Qualifiers sub-specifying the content that is being pushed - see comments
+  // on [Qualifier][build.bazel.remote.asset.v1.Qualifier].
+  // The same qualifiers apply to all URIs.
+  repeated Qualifier qualifiers = 3;
+
+  // A time after which this content should stop being returned via
+  // [FetchDirectory][build.bazel.remote.asset.v1.Fetch.FetchDirectory].
+  // Servers *MAY* expire content early, e.g. due to storage pressure.
+  google.protobuf.Timestamp expire_at = 4;
+
+  // Directory to associate
+  build.bazel.remote.execution.v2.Digest root_directory_digest = 5;
+
+  // Referenced blobs or directories that need to not expire before expiration
+  // of this association, in addition to `root_directory_digest` itself.
+  // These fields are hints - clients *MAY* omit them, and servers *SHOULD*
+  // respect them, at the risk of increased incidents of Fetch responses
+  // indirectly referencing unavailable blobs.
+  repeated build.bazel.remote.execution.v2.Digest references_blobs = 6;
+  repeated build.bazel.remote.execution.v2.Digest references_directories = 7;
+}
+
+// A response message for
+// [Push.PushDirectory][build.bazel.remote.asset.v1.Push.PushDirectory].
+message PushDirectoryResponse { /* empty */ }
diff --git a/third_party/remoteapis/build/bazel/remote/execution/v2/remote_execution.proto b/third_party/remoteapis/build/bazel/remote/execution/v2/remote_execution.proto
index ee4b0b8..efbf513 100644
--- a/third_party/remoteapis/build/bazel/remote/execution/v2/remote_execution.proto
+++ b/third_party/remoteapis/build/bazel/remote/execution/v2/remote_execution.proto
@@ -323,6 +323,8 @@
   // If part of the tree is missing from the CAS, the server will return the
   // portion present and omit the rest.
   //
+  // Errors:
+  //
   // * `NOT_FOUND`: The requested tree root is not present in the CAS.
   rpc GetTree(GetTreeRequest) returns (stream GetTreeResponse) {
     option (google.api.http) = { get: "/v2/{instance_name=**}/blobs/{root_digest.hash}/{root_digest.size_bytes}:getTree" };
@@ -410,6 +412,16 @@
   // If true, then the `Action`'s result cannot be cached, and in-flight
   // requests for the same `Action` may not be merged.
   bool do_not_cache = 7;
+
+  // List of required supported [NodeProperty][build.bazel.remote.execution.v2.NodeProperty]
+  // keys. In order to ensure that equivalent `Action`s always hash to the same
+  // value, the supported node properties MUST be lexicographically sorted by name.
+  // Sorting of strings is done by code point, equivalently, by the UTF-8 bytes.
+  //
+  // The interpretation of these properties is server-dependent. If a property is
+  // not recognized by the server, the server will return an `INVALID_ARGUMENT`
+  // error.
+  repeated string output_node_properties = 8;
 }
 
 // A `Command` is the actual command executed by a worker running an
@@ -466,6 +478,8 @@
   //
   // Directories leading up to the output files are created by the worker prior
   // to execution, even if they are not explicitly part of the input root.
+  //
+  // DEPRECATED since v2.1: Use `output_paths` instead.
   repeated string output_files = 3;
 
   // A list of the output directories that the client expects to retrieve from
@@ -495,8 +509,40 @@
   // Directories leading up to the output directories (but not the output
   // directories themselves) are created by the worker prior to execution, even
   // if they are not explicitly part of the input root.
+  //
+  // DEPRECATED since 2.1: Use `output_paths` instead.
   repeated string output_directories = 4;
 
+  // A list of the output paths that the client expects to retrieve from the
+  // action. Only the listed paths will be returned to the client as output.
+  // The type of the output (file or directory) is not specified, and will be
+  // determined by the server after action execution. If the resulting path is
+  // a file, it will be returned in an
+  // [OutputFile][build.bazel.remote.execution.v2.OutputFile]) typed field.
+  // If the path is a directory, the entire directory structure will be returned
+  // as a [Tree][build.bazel.remote.execution.v2.Tree] message digest, see
+  // [OutputDirectory][build.bazel.remote.execution.v2.OutputDirectory])
+  // Other files or directories that may be created during command execution
+  // are discarded.
+  //
+  // The paths are relative to the working directory of the action execution.
+  // The paths are specified using a single forward slash (`/`) as a path
+  // separator, even if the execution platform natively uses a different
+  // separator. The path MUST NOT include a trailing slash, nor a leading slash,
+  // being a relative path.
+  //
+  // In order to ensure consistent hashing of the same Action, the output paths
+  // MUST be deduplicated and sorted lexicographically by code point (or,
+  // equivalently, by UTF-8 bytes).
+  //
+  // Directories leading up to the output paths are created by the worker prior
+  // to execution, even if they are not explicitly part of the input root.
+  //
+  // New in v2.1: this field supersedes the DEPRECATED `output_files` and
+  // `output_directories` fields. If `output_paths` is used, `output_files` and
+  // `output_directories` will be ignored!
+  repeated string output_paths = 7;
+
   // The platform requirements for the execution environment. The server MAY
   // choose to execute the action on any worker satisfying the requirements, so
   // the client SHOULD ensure that running the action on any such worker will
@@ -571,6 +617,9 @@
 // * The files, directories and symlinks in the directory must each be sorted
 //   in lexicographical order by path. The path strings must be sorted by code
 //   point, equivalently, by UTF-8 bytes.
+// * The [NodeProperties][build.bazel.remote.execution.v2.NodeProperty] of files,
+//   directories, and symlinks must be sorted in lexicographical order by
+//   property name.
 //
 // A `Directory` that obeys the restrictions is said to be in canonical form.
 //
@@ -587,7 +636,13 @@
 //       digest: {
 //         hash: "4a73bc9d03...",
 //         size: 65534
-//       }
+//       },
+//       node_properties: [
+//         {
+//           "name": "MTime",
+//           "value": "2017-01-15T01:30:15.01Z"
+//         }
+//       ]
 //     }
 //   ],
 //   directories: [
@@ -624,6 +679,22 @@
 
   // The symlinks in the directory.
   repeated SymlinkNode symlinks = 3;
+
+  // The node properties of the Directory.
+  repeated NodeProperty node_properties = 4;
+}
+
+// A single property for [FileNodes][build.bazel.remote.execution.v2.FileNode],
+// [DirectoryNodes][build.bazel.remote.execution.v2.DirectoryNode], and
+// [SymlinkNodes][build.bazel.remote.execution.v2.SymlinkNode]. The server is
+// responsible for specifying the property `name`s that it accepts. If
+// permitted by the server, the same `name` may occur multiple times.
+message NodeProperty {
+    // The property name.
+    string name = 1;
+
+    // The property value.
+    string value = 2;
 }
 
 // A `FileNode` represents a single file and associated metadata.
@@ -638,6 +709,9 @@
 
   // True if file is executable, false otherwise.
   bool is_executable = 4;
+
+  // The node properties of the FileNode.
+  repeated NodeProperty node_properties = 5;
 }
 
 // A `DirectoryNode` represents a child of a
@@ -666,11 +740,13 @@
   // API. The canonical form forbids the substrings `/./` and `//` in the target
   // path. `..` components are allowed anywhere in the target path.
   string target = 2;
+
+  // The node properties of the SymlinkNode.
+  repeated NodeProperty node_properties = 3;
 }
 
 // A content digest. A digest for a given blob consists of the size of the blob
-// and its hash. The hash algorithm to use is defined by the server, but servers
-// SHOULD use SHA-256.
+// and its hash. The hash algorithm to use is defined by the server.
 //
 // The size is considered to be an integral part of the digest and cannot be
 // separated. That is, even if the `hash` field is correctly specified but
@@ -748,12 +824,12 @@
   reserved 1; // Reserved for use as the resource name.
 
   // The output files of the action. For each output file requested in the
-  // `output_files` field of the Action, if the corresponding file existed after
-  // the action completed, a single entry will be present either in this field,
-  // or the `output_file_symlinks` field if the file was a symbolic link to
-  // another file.
+  // `output_files` or `output_paths` field of the Action, if the corresponding
+  // file existed after the action completed, a single entry will be present
+  // either in this field, or the `output_file_symlinks` field if the file was
+  // a symbolic link to another file (`output_symlinks` field after v2.1).
   //
-  // If an output of the same name was found, but was a directory rather
+  // If an output listed in `output_files` was found, but was a directory rather
   // than a regular file, the server will return a FAILED_PRECONDITION.
   // If the action does not produce the requested output, then that output
   // will be omitted from the list. The server is free to arrange the output
@@ -764,22 +840,42 @@
   // may be links to other output files, or input files, or even absolute paths
   // outside of the working directory, if the server supports
   // [SymlinkAbsolutePathStrategy.ALLOWED][build.bazel.remote.execution.v2.CacheCapabilities.SymlinkAbsolutePathStrategy].
-  // For each output file requested in the `output_files` field of the Action,
-  // if the corresponding file existed after
+  // For each output file requested in the `output_files` or `output_paths`
+  // field of the Action, if the corresponding file existed after
   // the action completed, a single entry will be present either in this field,
   // or in the `output_files` field, if the file was not a symbolic link.
   //
-  // If an output symbolic link of the same name was found, but its target
-  // type was not a regular file, the server will return a FAILED_PRECONDITION.
+  // If an output symbolic link of the same name as listed in `output_files` of
+  // the Command was found, but its target type was not a regular file, the
+  // server will return a FAILED_PRECONDITION.
   // If the action does not produce the requested output, then that output
   // will be omitted from the list. The server is free to arrange the output
   // list as desired; clients MUST NOT assume that the output list is sorted.
+  //
+  // DEPRECATED as of v2.1. Servers that wish to be compatible with v2.0 API
+  // should still populate this field in addition to `output_symlinks`.
   repeated OutputSymlink output_file_symlinks = 10;
 
+  // New in v2.1: this field will only be populated if the command
+  // `output_paths` field was used, and not the pre v2.1 `output_files` or
+  // `output_directories` fields.
+  // The output paths of the action that are symbolic links to other paths. Those
+  // may be links to other outputs, or inputs, or even absolute paths
+  // outside of the working directory, if the server supports
+  // [SymlinkAbsolutePathStrategy.ALLOWED][build.bazel.remote.execution.v2.CacheCapabilities.SymlinkAbsolutePathStrategy].
+  // A single entry for each output requested in `output_paths`
+  // field of the Action, if the corresponding path existed after
+  // the action completed and was a symbolic link.
+  //
+  // If the action does not produce a requested output, then that output
+  // will be omitted from the list. The server is free to arrange the output
+  // list as desired; clients MUST NOT assume that the output list is sorted.
+  repeated OutputSymlink output_symlinks = 12;
+
   // The output directories of the action. For each output directory requested
-  // in the `output_directories` field of the Action, if the corresponding
-  // directory existed after the action completed, a single entry will be
-  // present in the output list, which will contain the digest of a
+  // in the `output_directories` or `output_paths` field of the Action, if the
+  // corresponding directory existed after the action completed, a single entry
+  // will be present in the output list, which will contain the digest of a
   // [Tree][build.bazel.remote.execution.v2.Tree] message containing the
   // directory tree, and the path equal exactly to the corresponding Action
   // output_directories member.
@@ -835,7 +931,8 @@
   //   }
   // }
   // ```
-  // If an output of the same name was found, but was not a directory, the
+  // If an output of the same name as listed in `output_files` of
+  // the Command was found in `output_directories`, but was not a directory, the
   // server will return a FAILED_PRECONDITION.
   repeated OutputDirectory output_directories = 3;
 
@@ -854,6 +951,9 @@
   // If the action does not produce the requested output, then that output
   // will be omitted from the list. The server is free to arrange the output
   // list as desired; clients MUST NOT assume that the output list is sorted.
+  //
+  // DEPRECATED as of v2.1. Servers that wish to be compatible with v2.0 API
+  // should still populate this field in addition to `output_symlinks`.
   repeated OutputSymlink output_directory_symlinks = 11;
 
   // The exit code of the command.
@@ -911,6 +1011,9 @@
   // message. The server MAY omit inlining, even if requested, and MUST do so if inlining
   // would cause the response to exceed message size limits.
   bytes contents = 5;
+
+  // The supported node properties of the OutputFile, if requested by the Action.
+  repeated NodeProperty node_properties = 6;
 }
 
 // A `Tree` contains all the
@@ -962,6 +1065,10 @@
   // API. The canonical form forbids the substrings `/./` and `//` in the target
   // path. `..` components are allowed anywhere in the target path.
   string target = 2;
+
+  // The supported node properties of the OutputSymlink, if requested by the
+  // Action.
+  repeated NodeProperty node_properties = 3;
 }
 
 // An `ExecutionPolicy` can be used to control the scheduling of the action.
@@ -1305,7 +1412,8 @@
 
   // A page token, which must be a value received in a previous
   // [GetTreeResponse][build.bazel.remote.execution.v2.GetTreeResponse].
-  // If present, the server will use it to return the following page of results.
+  // If present, the server will use that token as an offset, returning only
+  // that page and the ones that succeed it.
   string page_token = 4;
 }
 
@@ -1359,10 +1467,10 @@
     // It is an error for the server to return this value.
     UNKNOWN = 0;
 
-    // The Sha-256 digest function.
+    // The SHA-256 digest function.
     SHA256 = 1;
 
-    // The Sha-1 digest function.
+    // The SHA-1 digest function.
     SHA1 = 2;
 
     // The MD5 digest function.
@@ -1371,6 +1479,12 @@
     // The Microsoft "VSO-Hash" paged SHA256 digest function.
     // See https://github.com/microsoft/BuildXL/blob/master/Documentation/Specs/PagedHash.md .
     VSO = 4;
+
+    // The SHA-384 digest function.
+    SHA384 = 5;
+
+    // The SHA-512 digest function.
+    SHA512 = 6;
   }
 }
 
@@ -1441,6 +1555,9 @@
 
   // Supported execution priority range.
   PriorityCapabilities execution_priority_capabilities = 3;
+
+  // Supported node properties.
+  repeated string supported_node_properties = 4;
 }
 
 // Details for the tool used to call the API.