// Copyright 2025 Google LLC
//
// 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 google.storagetransfer.v1;

import "google/api/field_behavior.proto";
import "google/api/resource.proto";
import "google/protobuf/duration.proto";
import "google/protobuf/timestamp.proto";
import "google/rpc/code.proto";
import "google/type/date.proto";
import "google/type/timeofday.proto";

option csharp_namespace = "Google.Cloud.StorageTransfer.V1";
option go_package = "cloud.google.com/go/storagetransfer/apiv1/storagetransferpb;storagetransferpb";
option java_outer_classname = "TransferTypes";
option java_package = "com.google.storagetransfer.v1.proto";
option php_namespace = "Google\\Cloud\\StorageTransfer\\V1";
option ruby_package = "Google::Cloud::StorageTransfer::V1";

// Google service account
message GoogleServiceAccount {
  // Email address of the service account.
  string account_email = 1;

  // Unique identifier for the service account.
  string subject_id = 2;
}

// AWS access key (see
// [AWS Security
// Credentials](https://docs.aws.amazon.com/general/latest/gr/aws-security-credentials.html)).
//
// For information on our data retention policy for user credentials, see
// [User credentials](/storage-transfer/docs/data-retention#user-credentials).
message AwsAccessKey {
  // Required. AWS access key ID.
  string access_key_id = 1 [(google.api.field_behavior) = REQUIRED];

  // Required. AWS secret access key. This field is not returned in RPC
  // responses.
  string secret_access_key = 2 [(google.api.field_behavior) = REQUIRED];
}

// Azure credentials
//
// For information on our data retention policy for user credentials, see
// [User credentials](/storage-transfer/docs/data-retention#user-credentials).
message AzureCredentials {
  // Required. Azure shared access signature (SAS).
  //
  // For more information about SAS, see
  // [Grant limited access to Azure Storage resources using shared access
  // signatures
  // (SAS)](https://docs.microsoft.com/en-us/azure/storage/common/storage-sas-overview).
  string sas_token = 2 [(google.api.field_behavior) = REQUIRED];
}

// Conditions that determine which objects are transferred. Applies only
// to Cloud Data Sources such as S3, Azure, and Cloud Storage.
//
// The "last modification time" refers to the time of the
// last change to the object's content or metadata — specifically, this is
// the `updated` property of Cloud Storage objects, the `LastModified` field
// of S3 objects, and the `Last-Modified` header of Azure blobs.
//
// Transfers with a [PosixFilesystem][google.storagetransfer.v1.PosixFilesystem]
// source or destination don't support `ObjectConditions`.
message ObjectConditions {
  // Ensures that objects are not transferred until a specific minimum time
  // has elapsed after the "last modification time". When a
  // [TransferOperation][google.storagetransfer.v1.TransferOperation] begins,
  // objects with a "last modification time" are transferred only if the elapsed
  // time between the
  // [start_time][google.storagetransfer.v1.TransferOperation.start_time] of the
  // `TransferOperation` and the "last modification time" of the object is equal
  // to or greater than the value of min_time_elapsed_since_last_modification`.
  // Objects that do not have a "last modification time" are also transferred.
  google.protobuf.Duration min_time_elapsed_since_last_modification = 1;

  // Ensures that objects are not transferred if a specific maximum time
  // has elapsed since the "last modification time".
  // When a [TransferOperation][google.storagetransfer.v1.TransferOperation]
  // begins, objects with a "last modification time" are transferred only if the
  // elapsed time between the
  // [start_time][google.storagetransfer.v1.TransferOperation.start_time] of the
  // `TransferOperation`and the "last modification time" of the object
  //  is less than the value of max_time_elapsed_since_last_modification`.
  // Objects that do not have a "last modification time" are also transferred.
  google.protobuf.Duration max_time_elapsed_since_last_modification = 2;

  // If you specify `include_prefixes`, Storage Transfer Service uses the items
  // in the `include_prefixes` array to determine which objects to include in a
  // transfer. Objects must start with one of the matching `include_prefixes`
  // for inclusion in the transfer. If
  // [exclude_prefixes][google.storagetransfer.v1.ObjectConditions.exclude_prefixes]
  // is specified, objects must not start with any of the `exclude_prefixes`
  // specified for inclusion in the transfer.
  //
  // The following are requirements of `include_prefixes`:
  //
  //   * Each include-prefix can contain any sequence of Unicode characters, to
  //     a max length of 1024 bytes when UTF8-encoded, and must not contain
  //     Carriage Return or Line Feed characters.  Wildcard matching and regular
  //     expression matching are not supported.
  //
  //   * Each include-prefix must omit the leading slash. For example, to
  //     include the object `s3://my-aws-bucket/logs/y=2015/requests.gz`,
  //     specify the include-prefix as `logs/y=2015/requests.gz`.
  //
  //   * None of the include-prefix values can be empty, if specified.
  //
  //   * Each include-prefix must include a distinct portion of the object
  //     namespace. No include-prefix may be a prefix of another
  //     include-prefix.
  //
  // The max size of `include_prefixes` is 1000.
  //
  // For more information, see [Filtering objects from
  // transfers](/storage-transfer/docs/filtering-objects-from-transfers).
  repeated string include_prefixes = 3;

  // If you specify `exclude_prefixes`, Storage Transfer Service uses the items
  // in the `exclude_prefixes` array to determine which objects to exclude from
  // a transfer. Objects must not start with one of the matching
  // `exclude_prefixes` for inclusion in a transfer.
  //
  // The following are requirements of `exclude_prefixes`:
  //
  //   * Each exclude-prefix can contain any sequence of Unicode characters, to
  //     a max length of 1024 bytes when UTF8-encoded, and must not contain
  //     Carriage Return or Line Feed characters.  Wildcard matching and regular
  //     expression matching are not supported.
  //
  //   * Each exclude-prefix must omit the leading slash. For example, to
  //     exclude the object `s3://my-aws-bucket/logs/y=2015/requests.gz`,
  //     specify the exclude-prefix as `logs/y=2015/requests.gz`.
  //
  //   * None of the exclude-prefix values can be empty, if specified.
  //
  //   * Each exclude-prefix must exclude a distinct portion of the object
  //     namespace. No exclude-prefix may be a prefix of another
  //     exclude-prefix.
  //
  //   * If
  //   [include_prefixes][google.storagetransfer.v1.ObjectConditions.include_prefixes]
  //   is specified, then each exclude-prefix must start with the value of a
  //   path explicitly included by `include_prefixes`.
  //
  // The max size of `exclude_prefixes` is 1000.
  //
  // For more information, see [Filtering objects from
  // transfers](/storage-transfer/docs/filtering-objects-from-transfers).
  repeated string exclude_prefixes = 4;

  // If specified, only objects with a "last modification time" on or after
  // this timestamp and objects that don't have a "last modification time" are
  // transferred.
  //
  // The `last_modified_since` and `last_modified_before` fields can be used
  // together for chunked data processing. For example, consider a script that
  // processes each day's worth of data at a time. For that you'd set each
  // of the fields as follows:
  //
  // *  `last_modified_since` to the start of the day
  //
  // *  `last_modified_before` to the end of the day
  google.protobuf.Timestamp last_modified_since = 5;

  // If specified, only objects with a "last modification time" before this
  // timestamp and objects that don't have a "last modification time" are
  // transferred.
  google.protobuf.Timestamp last_modified_before = 6;
}

// In a GcsData resource, an object's name is the Cloud Storage object's
// name and its "last modification time" refers to the object's `updated`
// property of Cloud Storage objects, which changes when the content or the
// metadata of the object is updated.
message GcsData {
  // Required. Cloud Storage bucket name. Must meet
  // [Bucket Name Requirements](/storage/docs/naming#requirements).
  string bucket_name = 1 [(google.api.field_behavior) = REQUIRED];

  // Root path to transfer objects.
  //
  // Must be an empty string or full path name that ends with a '/'. This field
  // is treated as an object prefix. As such, it should generally not begin with
  // a '/'.
  //
  // The root path value must meet
  // [Object Name Requirements](/storage/docs/naming#objectnames).
  string path = 3;

  // Preview. Enables the transfer of managed folders between Cloud Storage
  // buckets. Set this option on the gcs_data_source.
  //
  // If set to true:
  //
  // - Managed folders in the source bucket are transferred to the
  //   destination bucket.
  // - Managed folders in the destination bucket are overwritten. Other
  //   OVERWRITE options are not supported.
  //
  // See
  // [Transfer Cloud Storage managed
  // folders](/storage-transfer/docs/managed-folders).
  bool managed_folder_transfer_enabled = 4;
}

// An AwsS3Data resource can be a data source, but not a data sink.
// In an AwsS3Data resource, an object's name is the S3 object's key name.
message AwsS3Data {
  // Required. S3 Bucket name (see
  // [Creating a
  // bucket](https://docs.aws.amazon.com/AmazonS3/latest/dev/create-bucket-get-location-example.html)).
  string bucket_name = 1 [(google.api.field_behavior) = REQUIRED];

  // Input only. AWS access key used to sign the API requests to the AWS S3
  // bucket. Permissions on the bucket must be granted to the access ID of the
  // AWS access key.
  //
  // For information on our data retention policy for user credentials, see
  // [User credentials](/storage-transfer/docs/data-retention#user-credentials).
  AwsAccessKey aws_access_key = 2 [(google.api.field_behavior) = INPUT_ONLY];

  // Root path to transfer objects.
  //
  // Must be an empty string or full path name that ends with a '/'. This field
  // is treated as an object prefix. As such, it should generally not begin with
  // a '/'.
  string path = 3;

  // The Amazon Resource Name (ARN) of the role to support temporary
  // credentials via `AssumeRoleWithWebIdentity`. For more information about
  // ARNs, see [IAM
  // ARNs](https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_identifiers.html#identifiers-arns).
  //
  // When a role ARN is provided, Transfer Service fetches temporary
  // credentials for the session using a `AssumeRoleWithWebIdentity` call for
  // the provided role using the
  // [GoogleServiceAccount][google.storagetransfer.v1.GoogleServiceAccount] for
  // this project.
  string role_arn = 4;

  // Optional. The CloudFront distribution domain name pointing to this bucket,
  // to use when fetching.
  //
  // See
  // [Transfer from S3 via
  // CloudFront](https://cloud.google.com/storage-transfer/docs/s3-cloudfront)
  // for more information.
  //
  // Format: `https://{id}.cloudfront.net` or any valid custom domain. Must
  // begin with `https://`.
  string cloudfront_domain = 6 [(google.api.field_behavior) = OPTIONAL];

  // Optional. The Resource name of a secret in Secret Manager.
  //
  // AWS credentials must be stored in Secret Manager in JSON format:
  //
  // {
  //  "access_key_id": "ACCESS_KEY_ID",
  //  "secret_access_key": "SECRET_ACCESS_KEY"
  // }
  //
  // [GoogleServiceAccount][google.storagetransfer.v1.GoogleServiceAccount] must
  // be granted `roles/secretmanager.secretAccessor` for the resource.
  //
  // See [Configure access to a source: Amazon S3]
  // (https://cloud.google.com/storage-transfer/docs/source-amazon-s3#secret_manager)
  // for more information.
  //
  // If `credentials_secret` is specified, do not specify
  // [role_arn][google.storagetransfer.v1.AwsS3Data.role_arn] or
  // [aws_access_key][google.storagetransfer.v1.AwsS3Data.aws_access_key].
  //
  // Format: `projects/{project_number}/secrets/{secret_name}`
  string credentials_secret = 7 [(google.api.field_behavior) = OPTIONAL];

  oneof private_network {
    // Egress bytes over a Google-managed private network.
    // This network is shared between other users of Storage Transfer Service.
    bool managed_private_network = 8;
  }
}

// An AzureBlobStorageData resource can be a data source, but not a data sink.
// An AzureBlobStorageData resource represents one Azure container. The storage
// account determines the [Azure
// endpoint](https://docs.microsoft.com/en-us/azure/storage/common/storage-create-storage-account#storage-account-endpoints).
// In an AzureBlobStorageData resource, a blobs's name is the [Azure Blob
// Storage blob's key
// name](https://docs.microsoft.com/en-us/rest/api/storageservices/naming-and-referencing-containers--blobs--and-metadata#blob-names).
message AzureBlobStorageData {
  // Required. The name of the Azure Storage account.
  string storage_account = 1 [(google.api.field_behavior) = REQUIRED];

  // Required. Input only. Credentials used to authenticate API requests to
  // Azure.
  //
  // For information on our data retention policy for user credentials, see
  // [User credentials](/storage-transfer/docs/data-retention#user-credentials).
  AzureCredentials azure_credentials = 2 [
    (google.api.field_behavior) = REQUIRED,
    (google.api.field_behavior) = INPUT_ONLY
  ];

  // Required. The container to transfer from the Azure Storage account.
  string container = 4 [(google.api.field_behavior) = REQUIRED];

  // Root path to transfer objects.
  //
  // Must be an empty string or full path name that ends with a '/'. This field
  // is treated as an object prefix. As such, it should generally not begin with
  // a '/'.
  string path = 5;

  // Optional. The Resource name of a secret in Secret Manager.
  //
  // The Azure SAS token must be stored in Secret Manager in JSON format:
  //
  // {
  //  "sas_token" : "SAS_TOKEN"
  // }
  //
  // [GoogleServiceAccount][google.storagetransfer.v1.GoogleServiceAccount] must
  // be granted `roles/secretmanager.secretAccessor` for the resource.
  //
  // See [Configure access to a source: Microsoft Azure Blob Storage]
  // (https://cloud.google.com/storage-transfer/docs/source-microsoft-azure#secret_manager)
  // for more information.
  //
  // If `credentials_secret` is specified, do not specify
  // [azure_credentials][google.storagetransfer.v1.AzureBlobStorageData.azure_credentials].
  //
  // Format: `projects/{project_number}/secrets/{secret_name}`
  string credentials_secret = 7 [(google.api.field_behavior) = OPTIONAL];
}

// An HttpData resource specifies a list of objects on the web to be
//  transferred over HTTP.  The information of the objects to be transferred is
//  contained in a file referenced by a URL. The first line in the file must be
//  `"TsvHttpData-1.0"`, which specifies the format of the file.  Subsequent
//  lines specify the information of the list of objects, one object per list
//  entry. Each entry has the following tab-delimited fields:
//
//  * **HTTP URL** — The location of the object.
//
//  * **Length** — The size of the object in bytes.
//
//  * **MD5** — The base64-encoded MD5 hash of the object.
//
//  For an example of a valid TSV file, see
//  [Transferring data from
//  URLs](https://cloud.google.com/storage-transfer/docs/create-url-list).
//
//  When transferring data based on a URL list, keep the following in mind:
//
// * When an object located at `http(s)://hostname:port/<URL-path>` is
//  transferred to a data sink, the name of the object at the data sink is
// `<hostname>/<URL-path>`.
//
// * If the specified size of an object does not match the actual size of the
//  object fetched, the object is not transferred.
//
// * If the specified MD5 does not match the MD5 computed from the transferred
//  bytes, the object transfer fails.
//
// * Ensure that each URL you specify is publicly accessible. For
//  example, in Cloud Storage you can
//  [share an object publicly]
//  (/storage/docs/cloud-console#_sharingdata) and get a link to it.
//
// * Storage Transfer Service obeys `robots.txt` rules and requires the source
//  HTTP server to support `Range` requests and to return a `Content-Length`
//  header in each response.
//
// * [ObjectConditions][google.storagetransfer.v1.ObjectConditions] have no
// effect when filtering objects to transfer.
message HttpData {
  // Required. The URL that points to the file that stores the object list
  // entries. This file must allow public access.  Currently, only URLs with
  // HTTP and HTTPS schemes are supported.
  string list_url = 1 [(google.api.field_behavior) = REQUIRED];
}

// A POSIX filesystem resource.
message PosixFilesystem {
  // Root directory path to the filesystem.
  string root_directory = 1;
}

// An HdfsData resource specifies a path within an HDFS entity (e.g. a cluster).
// All cluster-specific settings, such as namenodes and ports, are configured on
// the transfer agents servicing requests, so HdfsData only contains the root
// path to the data in our transfer.
message HdfsData {
  // Root path to transfer files.
  string path = 1;
}

// An AwsS3CompatibleData resource.
message AwsS3CompatibleData {
  // Required. Specifies the name of the bucket.
  string bucket_name = 1 [(google.api.field_behavior) = REQUIRED];

  // Specifies the root path to transfer objects.
  //
  // Must be an empty string or full path name that ends with a '/'. This
  // field is treated as an object prefix. As such, it should generally not
  // begin with a '/'.
  string path = 2;

  // Required. Specifies the endpoint of the storage service.
  string endpoint = 3 [(google.api.field_behavior) = REQUIRED];

  // Specifies the region to sign requests with. This can be left blank if
  // requests should be signed with an empty region.
  string region = 5;

  // Specifies the metadata of the S3 compatible data provider. Each provider
  // may contain some attributes that do not apply to all S3-compatible data
  // providers. When not specified, S3CompatibleMetadata is used by default.
  oneof data_provider {
    // A S3 compatible metadata.
    S3CompatibleMetadata s3_metadata = 4;
  }
}

// S3CompatibleMetadata contains the metadata fields that apply to the basic
// types of S3-compatible data providers.
message S3CompatibleMetadata {
  // The authentication and authorization method used by the storage service.
  enum AuthMethod {
    // AuthMethod is not specified.
    AUTH_METHOD_UNSPECIFIED = 0;

    // Auth requests with AWS SigV4.
    AUTH_METHOD_AWS_SIGNATURE_V4 = 1;

    // Auth requests with AWS SigV2.
    AUTH_METHOD_AWS_SIGNATURE_V2 = 2;
  }

  // The request model of the API.
  enum RequestModel {
    // RequestModel is not specified.
    REQUEST_MODEL_UNSPECIFIED = 0;

    // Perform requests using Virtual Hosted Style.
    // Example: https://bucket-name.s3.region.amazonaws.com/key-name
    REQUEST_MODEL_VIRTUAL_HOSTED_STYLE = 1;

    // Perform requests using Path Style.
    // Example: https://s3.region.amazonaws.com/bucket-name/key-name
    REQUEST_MODEL_PATH_STYLE = 2;
  }

  // The agent network protocol to access the storage service.
  enum NetworkProtocol {
    // NetworkProtocol is not specified.
    NETWORK_PROTOCOL_UNSPECIFIED = 0;

    // Perform requests using HTTPS.
    NETWORK_PROTOCOL_HTTPS = 1;

    // Not recommended: This sends data in clear-text. This is only
    // appropriate within a closed network or for publicly available data.
    // Perform requests using HTTP.
    NETWORK_PROTOCOL_HTTP = 2;
  }

  // The Listing API to use for discovering objects.
  enum ListApi {
    // ListApi is not specified.
    LIST_API_UNSPECIFIED = 0;

    // Perform listing using ListObjectsV2 API.
    LIST_OBJECTS_V2 = 1;

    // Legacy ListObjects API.
    LIST_OBJECTS = 2;
  }

  // Specifies the authentication and authorization method used by the storage
  // service. When not specified, Transfer Service will attempt to determine
  // right auth method to use.
  AuthMethod auth_method = 1;

  // Specifies the API request model used to call the storage service. When not
  // specified, the default value of RequestModel
  // REQUEST_MODEL_VIRTUAL_HOSTED_STYLE is used.
  RequestModel request_model = 2;

  // Specifies the network protocol of the agent. When not specified, the
  // default value of NetworkProtocol NETWORK_PROTOCOL_HTTPS is used.
  NetworkProtocol protocol = 3;

  // The Listing API to use for discovering objects. When not specified,
  // Transfer Service will attempt to determine the right API to use.
  ListApi list_api = 4;
}

// Represents an agent pool.
message AgentPool {
  option (google.api.resource) = {
    type: "storagetransfer.googleapis.com/agentPools"
    pattern: "projects/{project_id}/agentPools/{agent_pool_id}"
  };

  // The state of an AgentPool.
  enum State {
    // Default value. This value is unused.
    STATE_UNSPECIFIED = 0;

    // This is an initialization state. During this stage, resources are
    // allocated for the AgentPool.
    CREATING = 1;

    // Determines that the AgentPool is created for use. At this state, Agents
    // can join the AgentPool and participate in the transfer jobs in that pool.
    CREATED = 2;

    // Determines that the AgentPool deletion has been initiated, and all the
    // resources are scheduled to be cleaned up and freed.
    DELETING = 3;
  }

  // Specifies a bandwidth limit for an agent pool.
  message BandwidthLimit {
    // Bandwidth rate in megabytes per second, distributed across all the agents
    // in the pool.
    int64 limit_mbps = 1;
  }

  // Required. Specifies a unique string that identifies the agent pool.
  //
  // Format: `projects/{project_id}/agentPools/{agent_pool_id}`
  string name = 2 [(google.api.field_behavior) = REQUIRED];

  // Specifies the client-specified AgentPool description.
  string display_name = 3;

  // Output only. Specifies the state of the AgentPool.
  State state = 4 [(google.api.field_behavior) = OUTPUT_ONLY];

  // Specifies the bandwidth limit details. If this field is unspecified, the
  // default value is set as 'No Limit'.
  BandwidthLimit bandwidth_limit = 5;
}

// TransferOptions define the actions to be performed on objects in a transfer.
message TransferOptions {
  // Specifies when to overwrite an object in the sink when an object with
  // matching name is found in the source.
  enum OverwriteWhen {
    // Overwrite behavior is unspecified.
    OVERWRITE_WHEN_UNSPECIFIED = 0;

    // Overwrites destination objects with the source objects, only if the
    // objects have the same name but different HTTP ETags or checksum values.
    DIFFERENT = 1;

    // Never overwrites a destination object if a source object has the
    // same name. In this case, the source object is not transferred.
    NEVER = 2;

    // Always overwrite the destination object with the source object, even if
    // the HTTP Etags or checksum values are the same.
    ALWAYS = 3;
  }

  // When to overwrite objects that already exist in the sink. The default is
  // that only objects that are different from the source are ovewritten. If
  // true, all objects in the sink whose name matches an object in the source
  // are overwritten with the source object.
  bool overwrite_objects_already_existing_in_sink = 1;

  // Whether objects that exist only in the sink should be deleted.
  //
  // **Note:** This option and
  // [delete_objects_from_source_after_transfer][google.storagetransfer.v1.TransferOptions.delete_objects_from_source_after_transfer]
  // are mutually exclusive.
  bool delete_objects_unique_in_sink = 2;

  // Whether objects should be deleted from the source after they are
  // transferred to the sink.
  //
  // **Note:** This option and
  // [delete_objects_unique_in_sink][google.storagetransfer.v1.TransferOptions.delete_objects_unique_in_sink]
  // are mutually exclusive.
  bool delete_objects_from_source_after_transfer = 3;

  // When to overwrite objects that already exist in the sink. If not set,
  // overwrite behavior is determined by
  // [overwrite_objects_already_existing_in_sink][google.storagetransfer.v1.TransferOptions.overwrite_objects_already_existing_in_sink].
  OverwriteWhen overwrite_when = 4;

  // Represents the selected metadata options for a transfer job.
  MetadataOptions metadata_options = 5;
}

// Configuration for running a transfer.
message TransferSpec {
  // The write sink for the data.
  oneof data_sink {
    // A Cloud Storage data sink.
    GcsData gcs_data_sink = 4;

    // A POSIX Filesystem data sink.
    PosixFilesystem posix_data_sink = 13;
  }

  // The read source of the data.
  oneof data_source {
    // A Cloud Storage data source.
    GcsData gcs_data_source = 1;

    // An AWS S3 data source.
    AwsS3Data aws_s3_data_source = 2;

    // An HTTP URL data source.
    HttpData http_data_source = 3;

    // A POSIX Filesystem data source.
    PosixFilesystem posix_data_source = 14;

    // An Azure Blob Storage data source.
    AzureBlobStorageData azure_blob_storage_data_source = 8;

    // An AWS S3 compatible data source.
    AwsS3CompatibleData aws_s3_compatible_data_source = 19;

    // An HDFS cluster data source.
    HdfsData hdfs_data_source = 20;
  }

  oneof intermediate_data_location {
    // For transfers between file systems, specifies a Cloud Storage bucket
    // to be used as an intermediate location through which to transfer data.
    //
    // See [Transfer data between file
    // systems](https://cloud.google.com/storage-transfer/docs/file-to-file) for
    // more information.
    GcsData gcs_intermediate_data_location = 16;
  }

  // Only objects that satisfy these object conditions are included in the set
  // of data source and data sink objects.  Object conditions based on
  // objects' "last modification time" do not exclude objects in a data sink.
  ObjectConditions object_conditions = 5;

  // If the option
  // [delete_objects_unique_in_sink][google.storagetransfer.v1.TransferOptions.delete_objects_unique_in_sink]
  // is `true` and time-based object conditions such as 'last modification time'
  // are specified, the request fails with an
  // [INVALID_ARGUMENT][google.rpc.Code.INVALID_ARGUMENT] error.
  TransferOptions transfer_options = 6;

  // A manifest file provides a list of objects to be transferred from the data
  // source. This field points to the location of the manifest file.
  // Otherwise, the entire source bucket is used. ObjectConditions still apply.
  TransferManifest transfer_manifest = 15;

  // Specifies the agent pool name associated with the posix data source. When
  // unspecified, the default name is used.
  string source_agent_pool_name = 17;

  // Specifies the agent pool name associated with the posix data sink. When
  // unspecified, the default name is used.
  string sink_agent_pool_name = 18;
}

// Specifies the configuration for a cross-bucket replication job. Cross-bucket
// replication copies new or updated objects from a source Cloud Storage bucket
// to a destination Cloud Storage bucket. Existing objects in the source bucket
// are not copied by a new cross-bucket replication job.
message ReplicationSpec {
  // The data source to be replicated.
  oneof data_source {
    // The Cloud Storage bucket from which to replicate objects.
    GcsData gcs_data_source = 1;
  }

  // The destination for replicated objects.
  oneof data_sink {
    // The Cloud Storage bucket to which to replicate objects.
    GcsData gcs_data_sink = 2;
  }

  // Object conditions that determine which objects are transferred. For
  // replication jobs, only `include_prefixes` and `exclude_prefixes` are
  // supported.
  ObjectConditions object_conditions = 3;

  // Specifies the metadata options to be applied during replication.
  // Delete options are not supported. If a delete option is specified, the
  // request fails with an [INVALID_ARGUMENT][google.rpc.Code.INVALID_ARGUMENT]
  // error.
  TransferOptions transfer_options = 4;
}

// Specifies the metadata options for running a transfer.
message MetadataOptions {
  // Whether symlinks should be skipped or preserved during a transfer job.
  enum Symlink {
    // Symlink behavior is unspecified.
    SYMLINK_UNSPECIFIED = 0;

    // Do not preserve symlinks during a transfer job.
    SYMLINK_SKIP = 1;

    // Preserve symlinks during a transfer job.
    SYMLINK_PRESERVE = 2;
  }

  // Options for handling file mode attribute.
  enum Mode {
    // Mode behavior is unspecified.
    MODE_UNSPECIFIED = 0;

    // Do not preserve mode during a transfer job.
    MODE_SKIP = 1;

    // Preserve mode during a transfer job.
    MODE_PRESERVE = 2;
  }

  // Options for handling file GID attribute.
  enum GID {
    // GID behavior is unspecified.
    GID_UNSPECIFIED = 0;

    // Do not preserve GID during a transfer job.
    GID_SKIP = 1;

    // Preserve GID during a transfer job.
    GID_NUMBER = 2;
  }

  // Options for handling file UID attribute.
  enum UID {
    // UID behavior is unspecified.
    UID_UNSPECIFIED = 0;

    // Do not preserve UID during a transfer job.
    UID_SKIP = 1;

    // Preserve UID during a transfer job.
    UID_NUMBER = 2;
  }

  // Options for handling Cloud Storage object ACLs.
  enum Acl {
    // ACL behavior is unspecified.
    ACL_UNSPECIFIED = 0;

    // Use the destination bucket's default object ACLS, if applicable.
    ACL_DESTINATION_BUCKET_DEFAULT = 1;

    // Preserve the object's original ACLs. This requires the service account
    // to have `storage.objects.getIamPolicy` permission for the source object.
    // [Uniform bucket-level
    // access](https://cloud.google.com/storage/docs/uniform-bucket-level-access)
    // must not be enabled on either the source or destination buckets.
    ACL_PRESERVE = 2;
  }

  // Options for handling Google Cloud Storage object storage class.
  enum StorageClass {
    // Storage class behavior is unspecified.
    STORAGE_CLASS_UNSPECIFIED = 0;

    // Use the destination bucket's default storage class.
    STORAGE_CLASS_DESTINATION_BUCKET_DEFAULT = 1;

    // Preserve the object's original storage class. This is only supported for
    // transfers from Google Cloud Storage buckets. REGIONAL and MULTI_REGIONAL
    // storage classes will be mapped to STANDARD to ensure they can be written
    // to the destination bucket.
    STORAGE_CLASS_PRESERVE = 2;

    // Set the storage class to STANDARD.
    STORAGE_CLASS_STANDARD = 3;

    // Set the storage class to NEARLINE.
    STORAGE_CLASS_NEARLINE = 4;

    // Set the storage class to COLDLINE.
    STORAGE_CLASS_COLDLINE = 5;

    // Set the storage class to ARCHIVE.
    STORAGE_CLASS_ARCHIVE = 6;
  }

  // Options for handling temporary holds for Google Cloud Storage objects.
  enum TemporaryHold {
    // Temporary hold behavior is unspecified.
    TEMPORARY_HOLD_UNSPECIFIED = 0;

    // Do not set a temporary hold on the destination object.
    TEMPORARY_HOLD_SKIP = 1;

    // Preserve the object's original temporary hold status.
    TEMPORARY_HOLD_PRESERVE = 2;
  }

  // Options for handling the KmsKey setting for Google Cloud Storage objects.
  enum KmsKey {
    // KmsKey behavior is unspecified.
    KMS_KEY_UNSPECIFIED = 0;

    // Use the destination bucket's default encryption settings.
    KMS_KEY_DESTINATION_BUCKET_DEFAULT = 1;

    // Preserve the object's original Cloud KMS customer-managed encryption key
    // (CMEK) if present. Objects that do not use a Cloud KMS encryption key
    // will be encrypted using the destination bucket's encryption settings.
    KMS_KEY_PRESERVE = 2;
  }

  // Options for handling `timeCreated` metadata for Google Cloud Storage
  // objects.
  enum TimeCreated {
    // TimeCreated behavior is unspecified.
    TIME_CREATED_UNSPECIFIED = 0;

    // Do not preserve the `timeCreated` metadata from the source object.
    TIME_CREATED_SKIP = 1;

    // Preserves the source object's `timeCreated` or `lastModified` metadata in
    // the `customTime` field in the destination object.  Note that any value
    // stored in the source object's `customTime` field will not be propagated
    // to the destination object.
    TIME_CREATED_PRESERVE_AS_CUSTOM_TIME = 2;
  }

  // Specifies how symlinks should be handled by the transfer. By default,
  // symlinks are not preserved. Only applicable to transfers involving
  // POSIX file systems, and ignored for other transfers.
  Symlink symlink = 1;

  // Specifies how each file's mode attribute should be handled by the transfer.
  // By default, mode is not preserved. Only applicable to transfers involving
  // POSIX file systems, and ignored for other transfers.
  Mode mode = 2;

  // Specifies how each file's POSIX group ID (GID) attribute should be handled
  // by the transfer. By default, GID is not preserved. Only applicable to
  // transfers involving POSIX file systems, and ignored for other transfers.
  GID gid = 3;

  // Specifies how each file's POSIX user ID (UID) attribute should be handled
  // by the transfer. By default, UID is not preserved. Only applicable to
  // transfers involving POSIX file systems, and ignored for other transfers.
  UID uid = 4;

  // Specifies how each object's ACLs should be preserved for transfers between
  // Google Cloud Storage buckets. If unspecified, the default behavior is the
  // same as ACL_DESTINATION_BUCKET_DEFAULT.
  Acl acl = 5;

  // Specifies the storage class to set on objects being transferred to Google
  // Cloud Storage buckets.  If unspecified, the default behavior is the same as
  // [STORAGE_CLASS_DESTINATION_BUCKET_DEFAULT][google.storagetransfer.v1.MetadataOptions.StorageClass.STORAGE_CLASS_DESTINATION_BUCKET_DEFAULT].
  StorageClass storage_class = 6;

  // Specifies how each object's temporary hold status should be preserved for
  // transfers between Google Cloud Storage buckets.  If unspecified, the
  // default behavior is the same as
  // [TEMPORARY_HOLD_PRESERVE][google.storagetransfer.v1.MetadataOptions.TemporaryHold.TEMPORARY_HOLD_PRESERVE].
  TemporaryHold temporary_hold = 7;

  // Specifies how each object's Cloud KMS customer-managed encryption key
  // (CMEK) is preserved for transfers between Google Cloud Storage buckets.  If
  // unspecified, the default behavior is the same as
  // [KMS_KEY_DESTINATION_BUCKET_DEFAULT][google.storagetransfer.v1.MetadataOptions.KmsKey.KMS_KEY_DESTINATION_BUCKET_DEFAULT].
  KmsKey kms_key = 8;

  // Specifies how each object's `timeCreated` metadata is preserved for
  // transfers. If unspecified, the default behavior is the same as
  // [TIME_CREATED_SKIP][google.storagetransfer.v1.MetadataOptions.TimeCreated.TIME_CREATED_SKIP].
  // This behavior is supported for transfers to Cloud Storage buckets from
  // Cloud Storage, Amazon S3, S3-compatible storage, and Azure sources.
  TimeCreated time_created = 9;
}

// Specifies where the manifest is located.
message TransferManifest {
  // Specifies the path to the manifest in Cloud Storage. The Google-managed
  // service account for the transfer must have `storage.objects.get`
  // permission for this object. An example path is
  // `gs://bucket_name/path/manifest.csv`.
  string location = 1;
}

// Transfers can be scheduled to recur or to run just once.
message Schedule {
  // Required. The start date of a transfer. Date boundaries are determined
  // relative to UTC time. If `schedule_start_date` and
  // [start_time_of_day][google.storagetransfer.v1.Schedule.start_time_of_day]
  // are in the past relative to the job's creation time, the transfer starts
  // the day after you schedule the transfer request.
  //
  // **Note:** When starting jobs at or near midnight UTC it is possible that
  // a job starts later than expected. For example, if you send an outbound
  // request on June 1 one millisecond prior to midnight UTC and the Storage
  // Transfer Service server receives the request on June 2, then it creates
  // a TransferJob with `schedule_start_date` set to June 2 and a
  // `start_time_of_day` set to midnight UTC. The first scheduled
  // [TransferOperation][google.storagetransfer.v1.TransferOperation] takes
  // place on June 3 at midnight UTC.
  google.type.Date schedule_start_date = 1
      [(google.api.field_behavior) = REQUIRED];

  // The last day a transfer runs. Date boundaries are determined relative to
  // UTC time. A job runs once per 24 hours within the following guidelines:
  //
  // *   If `schedule_end_date` and
  // [schedule_start_date][google.storagetransfer.v1.Schedule.schedule_start_date]
  // are the same and in
  //     the future relative to UTC, the transfer is executed only one time.
  // *   If `schedule_end_date` is later than `schedule_start_date`  and
  //     `schedule_end_date` is in the future relative to UTC, the job runs each
  //     day at
  //     [start_time_of_day][google.storagetransfer.v1.Schedule.start_time_of_day]
  //     through `schedule_end_date`.
  google.type.Date schedule_end_date = 2;

  // The time in UTC that a transfer job is scheduled to run. Transfers may
  // start later than this time.
  //
  // If `start_time_of_day` is not specified:
  //
  // *   One-time transfers run immediately.
  // *   Recurring transfers run immediately, and each day at midnight UTC,
  //     through
  //     [schedule_end_date][google.storagetransfer.v1.Schedule.schedule_end_date].
  //
  // If `start_time_of_day` is specified:
  //
  // *   One-time transfers run at the specified time.
  // *   Recurring transfers run at the specified time each day, through
  //     `schedule_end_date`.
  google.type.TimeOfDay start_time_of_day = 3;

  // The time in UTC that no further transfer operations are scheduled. Combined
  // with
  // [schedule_end_date][google.storagetransfer.v1.Schedule.schedule_end_date],
  // `end_time_of_day` specifies the end date and time for starting new transfer
  // operations. This field must be greater than or equal to the timestamp
  // corresponding to the combintation of
  // [schedule_start_date][google.storagetransfer.v1.Schedule.schedule_start_date]
  // and
  // [start_time_of_day][google.storagetransfer.v1.Schedule.start_time_of_day],
  // and is subject to the following:
  //
  // *   If `end_time_of_day` is not set and `schedule_end_date` is set, then
  //     a default value of `23:59:59` is used for `end_time_of_day`.
  //
  // *   If `end_time_of_day` is set and `schedule_end_date` is not set, then
  //     [INVALID_ARGUMENT][google.rpc.Code.INVALID_ARGUMENT] is returned.
  google.type.TimeOfDay end_time_of_day = 4;

  // Interval between the start of each scheduled TransferOperation. If
  // unspecified, the default value is 24 hours. This value may not be less than
  // 1 hour.
  google.protobuf.Duration repeat_interval = 5;
}

// Specifies the Event-driven transfer options. Event-driven transfers listen to
// an event stream to transfer updated files.
message EventStream {
  // Required. Specifies a unique name of the resource such as AWS SQS
  // ARN in the form 'arn:aws:sqs:region:account_id:queue_name',
  // or Pub/Sub subscription resource name in the form
  // 'projects/{project}/subscriptions/{sub}'.
  string name = 1 [(google.api.field_behavior) = REQUIRED];

  // Specifies the date and time that Storage Transfer Service starts
  // listening for events from this stream. If no start time is specified or
  // start time is in the past, Storage Transfer Service starts listening
  // immediately.
  google.protobuf.Timestamp event_stream_start_time = 2;

  // Specifies the data and time at which Storage Transfer Service stops
  // listening for events from this stream. After this time, any transfers in
  // progress will complete, but no new transfers are initiated.
  google.protobuf.Timestamp event_stream_expiration_time = 3;
}

// This resource represents the configuration of a transfer job that runs
// periodically.
message TransferJob {
  // The status of the transfer job.
  enum Status {
    // Zero is an illegal value.
    STATUS_UNSPECIFIED = 0;

    // New transfers are performed based on the schedule.
    ENABLED = 1;

    // New transfers are not scheduled.
    DISABLED = 2;

    // This is a soft delete state. After a transfer job is set to this
    // state, the job and all the transfer executions are subject to
    // garbage collection. Transfer jobs become eligible for garbage collection
    // 30 days after their status is set to `DELETED`.
    DELETED = 3;
  }

  // A unique name (within the transfer project) assigned when the job is
  // created.  If this field is empty in a CreateTransferJobRequest, Storage
  // Transfer Service assigns a unique name. Otherwise, the specified name
  // is used as the unique name for this job.
  //
  // If the specified name is in use by a job, the creation request fails with
  // an [ALREADY_EXISTS][google.rpc.Code.ALREADY_EXISTS] error.
  //
  // This name must start with `"transferJobs/"` prefix and end with a letter or
  // a number, and should be no more than 128 characters. For transfers
  // involving PosixFilesystem, this name must start with `transferJobs/OPI`
  // specifically. For all other transfer types, this name must not start with
  // `transferJobs/OPI`.
  //
  // Non-PosixFilesystem example:
  // `"transferJobs/^(?!OPI)[A-Za-z0-9-._~]*[A-Za-z0-9]$"`
  //
  // PosixFilesystem example:
  // `"transferJobs/OPI^[A-Za-z0-9-._~]*[A-Za-z0-9]$"`
  //
  // Applications must not rely on the enforcement of naming requirements
  // involving OPI.
  //
  // Invalid job names fail with an
  // [INVALID_ARGUMENT][google.rpc.Code.INVALID_ARGUMENT] error.
  string name = 1;

  // A description provided by the user for the job. Its max length is 1024
  // bytes when Unicode-encoded.
  string description = 2;

  // The ID of the Google Cloud project that owns the job.
  string project_id = 3;

  // Transfer specification.
  TransferSpec transfer_spec = 4;

  // Replication specification.
  ReplicationSpec replication_spec = 17;

  // Notification configuration.
  NotificationConfig notification_config = 11;

  // Logging configuration.
  LoggingConfig logging_config = 14;

  // Specifies schedule for the transfer job.
  // This is an optional field. When the field is not set, the job never
  // executes a transfer, unless you invoke RunTransferJob or update the job to
  // have a non-empty schedule.
  Schedule schedule = 5;

  // Specifies the event stream for the transfer job for event-driven transfers.
  // When EventStream is specified, the Schedule fields are ignored.
  EventStream event_stream = 15;

  // Status of the job. This value MUST be specified for
  // `CreateTransferJobRequests`.
  //
  // **Note:** The effect of the new job status takes place during a subsequent
  // job run. For example, if you change the job status from
  // [ENABLED][google.storagetransfer.v1.TransferJob.Status.ENABLED] to
  // [DISABLED][google.storagetransfer.v1.TransferJob.Status.DISABLED], and an
  // operation spawned by the transfer is running, the status change would not
  // affect the current operation.
  Status status = 6;

  // Output only. The time that the transfer job was created.
  google.protobuf.Timestamp creation_time = 7
      [(google.api.field_behavior) = OUTPUT_ONLY];

  // Output only. The time that the transfer job was last modified.
  google.protobuf.Timestamp last_modification_time = 8
      [(google.api.field_behavior) = OUTPUT_ONLY];

  // Output only. The time that the transfer job was deleted.
  google.protobuf.Timestamp deletion_time = 9
      [(google.api.field_behavior) = OUTPUT_ONLY];

  // The name of the most recently started TransferOperation of this JobConfig.
  // Present if a TransferOperation has been created for this JobConfig.
  string latest_operation_name = 12;
}

// An entry describing an error that has occurred.
message ErrorLogEntry {
  // Required. A URL that refers to the target (a data source, a data sink,
  // or an object) with which the error is associated.
  string url = 1 [(google.api.field_behavior) = REQUIRED];

  // A list of messages that carry the error details.
  repeated string error_details = 3;
}

// A summary of errors by error code, plus a count and sample error log
// entries.
message ErrorSummary {
  // Required.
  google.rpc.Code error_code = 1 [(google.api.field_behavior) = REQUIRED];

  // Required. Count of this type of error.
  int64 error_count = 2 [(google.api.field_behavior) = REQUIRED];

  // Error samples.
  //
  // At most 5 error log entries are recorded for a given
  // error code for a single transfer operation.
  repeated ErrorLogEntry error_log_entries = 3;
}

// A collection of counters that report the progress of a transfer operation.
message TransferCounters {
  // Objects found in the data source that are scheduled to be transferred,
  // excluding any that are filtered based on object conditions or skipped due
  // to sync.
  int64 objects_found_from_source = 1;

  // Bytes found in the data source that are scheduled to be transferred,
  // excluding any that are filtered based on object conditions or skipped due
  // to sync.
  int64 bytes_found_from_source = 2;

  // Objects found only in the data sink that are scheduled to be deleted.
  int64 objects_found_only_from_sink = 3;

  // Bytes found only in the data sink that are scheduled to be deleted.
  int64 bytes_found_only_from_sink = 4;

  // Objects in the data source that are not transferred because they already
  // exist in the data sink.
  int64 objects_from_source_skipped_by_sync = 5;

  // Bytes in the data source that are not transferred because they already
  // exist in the data sink.
  int64 bytes_from_source_skipped_by_sync = 6;

  // Objects that are copied to the data sink.
  int64 objects_copied_to_sink = 7;

  // Bytes that are copied to the data sink.
  int64 bytes_copied_to_sink = 8;

  // Objects that are deleted from the data source.
  int64 objects_deleted_from_source = 9;

  // Bytes that are deleted from the data source.
  int64 bytes_deleted_from_source = 10;

  // Objects that are deleted from the data sink.
  int64 objects_deleted_from_sink = 11;

  // Bytes that are deleted from the data sink.
  int64 bytes_deleted_from_sink = 12;

  // Objects in the data source that failed to be transferred or that failed
  // to be deleted after being transferred.
  int64 objects_from_source_failed = 13;

  // Bytes in the data source that failed to be transferred or that failed to
  // be deleted after being transferred.
  int64 bytes_from_source_failed = 14;

  // Objects that failed to be deleted from the data sink.
  int64 objects_failed_to_delete_from_sink = 15;

  // Bytes that failed to be deleted from the data sink.
  int64 bytes_failed_to_delete_from_sink = 16;

  // For transfers involving PosixFilesystem only.
  //
  // Number of directories found while listing. For example, if the root
  // directory of the transfer is `base/` and there are two other directories,
  // `a/` and `b/` under this directory, the count after listing `base/`,
  // `base/a/` and `base/b/` is 3.
  int64 directories_found_from_source = 17;

  // For transfers involving PosixFilesystem only.
  //
  // Number of listing failures for each directory found at the source.
  // Potential failures when listing a directory include permission failure or
  // block failure. If listing a directory fails, no files in the directory are
  // transferred.
  int64 directories_failed_to_list_from_source = 18;

  // For transfers involving PosixFilesystem only.
  //
  // Number of successful listings for each directory found at the source.
  int64 directories_successfully_listed_from_source = 19;

  // Number of successfully cleaned up intermediate objects.
  int64 intermediate_objects_cleaned_up = 22;

  // Number of intermediate objects failed cleaned up.
  int64 intermediate_objects_failed_cleaned_up = 23;
}

// Specification to configure notifications published to Pub/Sub.
// Notifications are published to the customer-provided topic using the
// following `PubsubMessage.attributes`:
//
// * `"eventType"`: one of the
// [EventType][google.storagetransfer.v1.NotificationConfig.EventType] values
// * `"payloadFormat"`: one of the
// [PayloadFormat][google.storagetransfer.v1.NotificationConfig.PayloadFormat]
// values
// * `"projectId"`: the
// [project_id][google.storagetransfer.v1.TransferOperation.project_id] of the
// `TransferOperation`
// * `"transferJobName"`: the
// [transfer_job_name][google.storagetransfer.v1.TransferOperation.transfer_job_name]
// of the `TransferOperation`
// * `"transferOperationName"`: the
// [name][google.storagetransfer.v1.TransferOperation.name] of the
// `TransferOperation`
//
// The `PubsubMessage.data` contains a
// [TransferOperation][google.storagetransfer.v1.TransferOperation] resource
// formatted according to the specified `PayloadFormat`.
message NotificationConfig {
  // Enum for specifying event types for which notifications are to be
  // published.
  //
  // Additional event types may be added in the future. Clients should either
  // safely ignore unrecognized event types or explicitly specify which event
  // types they are prepared to accept.
  enum EventType {
    // Illegal value, to avoid allowing a default.
    EVENT_TYPE_UNSPECIFIED = 0;

    // `TransferOperation` completed with status
    // [SUCCESS][google.storagetransfer.v1.TransferOperation.Status.SUCCESS].
    TRANSFER_OPERATION_SUCCESS = 1;

    // `TransferOperation` completed with status
    // [FAILED][google.storagetransfer.v1.TransferOperation.Status.FAILED].
    TRANSFER_OPERATION_FAILED = 2;

    // `TransferOperation` completed with status
    // [ABORTED][google.storagetransfer.v1.TransferOperation.Status.ABORTED].
    TRANSFER_OPERATION_ABORTED = 3;
  }

  // Enum for specifying the format of a notification message's payload.
  enum PayloadFormat {
    // Illegal value, to avoid allowing a default.
    PAYLOAD_FORMAT_UNSPECIFIED = 0;

    // No payload is included with the notification.
    NONE = 1;

    // `TransferOperation` is [formatted as a JSON
    // response](https://developers.google.com/protocol-buffers/docs/proto3#json),
    // in application/json.
    JSON = 2;
  }

  // Required. The `Topic.name` of the Pub/Sub topic to which to publish
  // notifications. Must be of the format: `projects/{project}/topics/{topic}`.
  // Not matching this format results in an
  // [INVALID_ARGUMENT][google.rpc.Code.INVALID_ARGUMENT] error.
  string pubsub_topic = 1 [(google.api.field_behavior) = REQUIRED];

  // Event types for which a notification is desired. If empty, send
  // notifications for all event types.
  repeated EventType event_types = 2;

  // Required. The desired format of the notification message payloads.
  PayloadFormat payload_format = 3 [(google.api.field_behavior) = REQUIRED];
}

// Specifies the logging behavior for transfer operations.
//
// Logs can be sent to Cloud Logging for all transfer types. See
// [Read transfer
// logs](https://cloud.google.com/storage-transfer/docs/read-transfer-logs) for
// details.
message LoggingConfig {
  // Loggable actions.
  enum LoggableAction {
    // Default value. This value is unused.
    LOGGABLE_ACTION_UNSPECIFIED = 0;

    // Listing objects in a bucket.
    FIND = 1;

    // Deleting objects at the source or the destination.
    DELETE = 2;

    // Copying objects to Google Cloud Storage.
    COPY = 3;
  }

  // Loggable action states.
  enum LoggableActionState {
    // Default value. This value is unused.
    LOGGABLE_ACTION_STATE_UNSPECIFIED = 0;

    // `LoggableAction` completed successfully. `SUCCEEDED` actions are
    // logged as [INFO][google.logging.type.LogSeverity.INFO].
    SUCCEEDED = 1;

    // `LoggableAction` terminated in an error state. `FAILED` actions are
    // logged as [ERROR][google.logging.type.LogSeverity.ERROR].
    FAILED = 2;
  }

  // Specifies the actions to be logged. If empty, no logs are generated.
  repeated LoggableAction log_actions = 1;

  // States in which `log_actions` are logged. If empty, no logs are generated.
  repeated LoggableActionState log_action_states = 2;

  // For PosixFilesystem transfers, enables
  // [file system transfer
  // logs](https://cloud.google.com/storage-transfer/docs/on-prem-transfer-log-format)
  // instead of, or in addition to, Cloud Logging.
  //
  // This option ignores [LoggableAction] and [LoggableActionState]. If these
  // are set, Cloud Logging will also be enabled for this transfer.
  bool enable_onprem_gcs_transfer_logs = 3;
}

// A description of the execution of a transfer.
message TransferOperation {
  // The status of a TransferOperation.
  enum Status {
    // Zero is an illegal value.
    STATUS_UNSPECIFIED = 0;

    // In progress.
    IN_PROGRESS = 1;

    // Paused.
    PAUSED = 2;

    // Completed successfully.
    SUCCESS = 3;

    // Terminated due to an unrecoverable failure.
    FAILED = 4;

    // Aborted by the user.
    ABORTED = 5;

    // Temporarily delayed by the system. No user action is required.
    QUEUED = 6;

    // The operation is suspending and draining the ongoing work to completion.
    SUSPENDING = 7;
  }

  // A globally unique ID assigned by the system.
  string name = 1;

  // The ID of the Google Cloud project that owns the operation.
  string project_id = 2;

  // Transfer specification.
  TransferSpec transfer_spec = 3;

  // Notification configuration.
  NotificationConfig notification_config = 10;

  // Cloud Logging configuration.
  LoggingConfig logging_config = 12;

  // Start time of this transfer execution.
  google.protobuf.Timestamp start_time = 4;

  // End time of this transfer execution.
  google.protobuf.Timestamp end_time = 5;

  // Status of the transfer operation.
  Status status = 6;

  // Information about the progress of the transfer operation.
  TransferCounters counters = 7;

  // Summarizes errors encountered with sample error log entries.
  repeated ErrorSummary error_breakdowns = 8;

  // The name of the transfer job that triggers this transfer operation.
  string transfer_job_name = 9;
}
