// Copyright 2026 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.cloud.ftp.v1;

import "google/api/annotations.proto";
import "google/api/client.proto";
import "google/api/field_behavior.proto";
import "google/api/field_info.proto";
import "google/api/resource.proto";
import "google/longrunning/operations.proto";
import "google/protobuf/empty.proto";
import "google/protobuf/field_mask.proto";
import "google/protobuf/timestamp.proto";

option csharp_namespace = "Google.Cloud.Ftp.V1";
option go_package = "cloud.google.com/go/ftp/apiv1/ftppb;ftppb";
option java_multiple_files = true;
option java_outer_classname = "ServiceProto";
option java_package = "com.google.cloud.ftp.v1";
option php_namespace = "Google\\Cloud\\Ftp\\V1";
option ruby_package = "Google::Cloud::Ftp::V1";
option (google.api.resource_definition) = {
  type: "compute.googleapis.com/ForwardingRule"
  pattern: "projects/{project}/regions/{region}/forwardingRules/{forwarding_rule}"
};
option (google.api.resource_definition) = {
  type: "compute.googleapis.com/Network"
  pattern: "projects/{project}/global/networks/{network}"
};
option (google.api.resource_definition) = {
  type: "compute.googleapis.com/ServiceAttachment"
  pattern: "projects/{project}/regions/{region}/serviceAttachments/{service_attachment}"
};

// Service describing handlers for resources
service CloudFtp {
  option (google.api.default_host) = "ftp.googleapis.com";
  option (google.api.oauth_scopes) =
      "https://www.googleapis.com/auth/cloud-platform";

  // Lists Servers in a given project and location.
  rpc ListServers(ListServersRequest) returns (ListServersResponse) {
    option (google.api.http) = {
      get: "/v1/{parent=projects/*/locations/*}/servers"
    };
    option (google.api.method_signature) = "parent";
  }

  // Gets details of a single Server.
  rpc GetServer(GetServerRequest) returns (Server) {
    option (google.api.http) = {
      get: "/v1/{name=projects/*/locations/*/servers/*}"
    };
    option (google.api.method_signature) = "name";
  }

  // Creates a new Server in a given project and location.
  rpc CreateServer(CreateServerRequest) returns (google.longrunning.Operation) {
    option (google.api.http) = {
      post: "/v1/{parent=projects/*/locations/*}/servers"
      body: "server"
    };
    option (google.api.method_signature) = "parent,server,server_id";
    option (google.longrunning.operation_info) = {
      response_type: "Server"
      metadata_type: "OperationMetadata"
    };
  }

  // Updates the parameters of a single Server.
  rpc UpdateServer(UpdateServerRequest) returns (google.longrunning.Operation) {
    option (google.api.http) = {
      patch: "/v1/{server.name=projects/*/locations/*/servers/*}"
      body: "server"
    };
    option (google.api.method_signature) = "server,update_mask";
    option (google.longrunning.operation_info) = {
      response_type: "Server"
      metadata_type: "OperationMetadata"
    };
  }

  // Deletes a single Server.
  rpc DeleteServer(DeleteServerRequest) returns (google.longrunning.Operation) {
    option (google.api.http) = {
      delete: "/v1/{name=projects/*/locations/*/servers/*}"
    };
    option (google.api.method_signature) = "name";
    option (google.longrunning.operation_info) = {
      response_type: "google.protobuf.Empty"
      metadata_type: "OperationMetadata"
    };
  }

  // Lists Users in a given project and location.
  rpc ListUsers(ListUsersRequest) returns (ListUsersResponse) {
    option (google.api.http) = {
      get: "/v1/{parent=projects/*/locations/*/servers/*}/users"
    };
    option (google.api.method_signature) = "parent";
  }

  // Gets details of a single User.
  rpc GetUser(GetUserRequest) returns (User) {
    option (google.api.http) = {
      get: "/v1/{name=projects/*/locations/*/servers/*/users/*}"
    };
    option (google.api.method_signature) = "name";
  }

  // Creates a new User in a given project and location and Server.
  rpc CreateUser(CreateUserRequest) returns (google.longrunning.Operation) {
    option (google.api.http) = {
      post: "/v1/{parent=projects/*/locations/*/servers/*}/users"
      body: "user"
    };
    option (google.api.method_signature) = "parent,user,user_id";
    option (google.longrunning.operation_info) = {
      response_type: "User"
      metadata_type: "OperationMetadata"
    };
  }

  // Updates the parameters of a single User.
  rpc UpdateUser(UpdateUserRequest) returns (google.longrunning.Operation) {
    option (google.api.http) = {
      patch: "/v1/{user.name=projects/*/locations/*/servers/*/users/*}"
      body: "user"
    };
    option (google.api.method_signature) = "user,update_mask";
    option (google.longrunning.operation_info) = {
      response_type: "User"
      metadata_type: "OperationMetadata"
    };
  }

  // Deletes a single User.
  rpc DeleteUser(DeleteUserRequest) returns (google.longrunning.Operation) {
    option (google.api.http) = {
      delete: "/v1/{name=projects/*/locations/*/servers/*/users/*}"
    };
    option (google.api.method_signature) = "name";
    option (google.longrunning.operation_info) = {
      response_type: "google.protobuf.Empty"
      metadata_type: "OperationMetadata"
    };
  }

  // Starts a stopping/stopped Server.
  rpc StartServer(StartServerRequest) returns (google.longrunning.Operation) {
    option (google.api.http) = {
      post: "/v1/{name=projects/*/locations/*/servers/*}:start"
      body: "*"
    };
    option (google.api.method_signature) = "name";
    option (google.longrunning.operation_info) = {
      response_type: "Server"
      metadata_type: "OperationMetadata"
    };
  }

  // Stops an active Server.
  rpc StopServer(StopServerRequest) returns (google.longrunning.Operation) {
    option (google.api.http) = {
      post: "/v1/{name=projects/*/locations/*/servers/*}:stop"
      body: "*"
    };
    option (google.api.method_signature) = "name";
    option (google.longrunning.operation_info) = {
      response_type: "Server"
      metadata_type: "OperationMetadata"
    };
  }
}

// View for Server resource.
enum ServerView {
  // Default value. Equivalent to SERVER_VIEW_BASIC.
  SERVER_VIEW_UNSPECIFIED = 0;

  // Basic view. Excludes heavy configurations (internal_config,
  // external_config, google_managed_server_credential).
  SERVER_VIEW_BASIC = 1;

  // Full view. Includes all fields.
  SERVER_VIEW_FULL = 2;
}

// View for User resource.
enum UserView {
  // Default value. Equivalent to USER_VIEW_BASIC.
  USER_VIEW_UNSPECIFIED = 0;

  // Basic view. Excludes heavy configurations (user_credentials,
  // storage_directory_mappings).
  USER_VIEW_BASIC = 1;

  // Full view. Includes all fields.
  USER_VIEW_FULL = 2;
}

// Configuration for external server.
message ExternalServerConfig {
  // Output only. IP address of the LB via which clients will connect.
  string ip_address = 1 [
    (google.api.field_info).format = IPV4_OR_IPV6,
    (google.api.field_behavior) = OUTPUT_ONLY
  ];

  // Optional. List of CIDR blocks that are allowed to access the Server.
  // A CIDR range consists of an IP Address and a prefix length to construct the
  // subnet mask. By default, the prefix length is 32 (i.e. matches a single IP
  // address). For now, only IPV4 addresses are supported.
  // Examples: "203.0.113.0/24" -
  // matches with the IP addresses in the range 203.0.113.0 - 203.0.113.255.
  // "0.0.0.0/0" - matches against any IP address.
  // This field must contain at least one entry if the access type is EXTERNAL.
  // The number of allowed CIDR blocks cannot exceed 500.
  // Example: 192.168.0.0/16
  repeated string allowed_cidr_blocks = 2
      [(google.api.field_behavior) = OPTIONAL];
}

// Configuration for private server accessible via PSC.
message InternalServerConfig {
  // A consumer project or network that is permitted to connect to the server
  // via PSC.
  message AllowedConsumer {
    // Required. Specifies the type of consumer.
    oneof consumer_type {
      // The project ID or number of the consumer project.
      // Must be in the format: `projects/{project}`.
      string project = 1 [(google.api.resource_reference) = {
        type: "cloudresourcemanager.googleapis.com/Project"
      }];
    }

    // Required. The connection limit for the consumer.
    // Value must be greater than 0.
    int64 connection_limit = 2 [(google.api.field_behavior) = REQUIRED];
  }

  // A consumer project or network that is denied to connect to the server via
  // PSC.
  message DeniedConsumer {
    // Required. Specifies the type of consumer.
    oneof consumer_type {
      // The project ID or number of the consumer project.
      // Must be in the format: `projects/{project}`.
      string project = 1 [(google.api.resource_reference) = {
        type: "cloudresourcemanager.googleapis.com/Project"
      }];
    }
  }

  // Details of PSC endpoint created by customer.
  message PscEndpoint {
    // Output only. This is a Resource name for Private Service Connect
    // endpoint. Format:
    // `projects/{project}/regions/{region}/forwardingRules/{forwarding_rule}`
    string endpoint = 1 [
      (google.api.field_behavior) = OUTPUT_ONLY,
      (google.api.resource_reference) = {
        type: "compute.googleapis.com/ForwardingRule"
      }
    ];

    // Output only. The consumer network.
    // Format: `projects/{project}/locations/{location}/networks/{network}`
    string network = 2 [
      (google.api.field_behavior) = OUTPUT_ONLY,
      (google.api.resource_reference) = {
        type: "compute.googleapis.com/Network"
      }
    ];

    // Output only. The status of the connected endpoint.
    string status = 3 [(google.api.field_behavior) = OUTPUT_ONLY];
  }

  // Output only. The resource name of the service attachment.
  // Format:
  // `projects/{project}/regions/{region}/serviceAttachments/{service_attachment}`
  string service_attachment = 1 [
    (google.api.field_behavior) = OUTPUT_ONLY,
    (google.api.resource_reference) = {
      type: "compute.googleapis.com/ServiceAttachment"
    }
  ];

  // Required. A list of projects that are permitted to connect.
  // At least one project is required in the allow list.
  repeated AllowedConsumer consumer_accept_list = 2
      [(google.api.field_behavior) = REQUIRED];

  // Optional. A list of projects that are denied connection.
  // Format: "projects/sample_project_id" or "projects/1234567890"
  // Projects in this list will be denied access, even if they are included in
  // the `allow_list`. If this list is empty, no projects are explicitly
  // rejected.
  repeated DeniedConsumer consumer_reject_list = 3
      [(google.api.field_behavior) = OPTIONAL];

  // Output only. Details of endpoints created by the customer.
  repeated PscEndpoint psc_endpoints = 4
      [(google.api.field_behavior) = OUTPUT_ONLY];
}

// Represents credentials of an FTP Server.
message ServerCredential {
  // Output only. The fingerprint is a hash of the public key, and is displayed
  // when clients access the server for the first time to verify the server's
  // identity.
  string fingerprint = 1 [(google.api.field_behavior) = OUTPUT_ONLY];

  // Output only. Asymmetric algorithm used by the public key.
  // Possible values (can be expanded in future):
  // - ssh-ed25519
  string asymmetric_algorithm = 2 [(google.api.field_behavior) = OUTPUT_ONLY];
}

// Message describing Server object
message Server {
  option (google.api.resource) = {
    type: "ftp.googleapis.com/Server"
    pattern: "projects/{project}/locations/{location}/servers/{server}"
    plural: "servers"
    singular: "server"
  };

  // The access type of the Server.
  enum AccessType {
    // Default value. This value is unused.
    ACCESS_TYPE_UNSPECIFIED = 0;

    // Server is assigned a public IP.
    EXTERNAL = 1;

    // Server is assigned an internal IP.
    INTERNAL = 2;
  }

  // Tracks Server status.
  enum State {
    // Default value. This value is unused.
    STATE_UNSPECIFIED = 0;

    // Server is being created.
    CREATING = 1;

    // Server is starting.
    STARTING = 2;

    // Server is ready to be used.
    ACTIVE = 3;

    // Server is stopping.
    STOPPING = 4;

    // Server is stopped.
    STOPPED = 5;

    // Server is being deleted.
    DELETING = 6;

    // Server is in error state.
    ERROR = 7;

    // Server is being updated.
    UPDATING = 8;
  }

  // Configuration for server access.
  // If this is set, it must match the value in the `access_type` field.
  oneof access_config {
    // Configuration for external access.
    ExternalServerConfig external_config = 7;

    // Configuration for internal access.
    InternalServerConfig internal_config = 8;
  }

  // Identifier. name of resource
  string name = 1 [(google.api.field_behavior) = IDENTIFIER];

  // Output only. [Output only] Create time stamp
  google.protobuf.Timestamp create_time = 2
      [(google.api.field_behavior) = OUTPUT_ONLY];

  // Output only. [Output only] Update time stamp
  google.protobuf.Timestamp update_time = 3
      [(google.api.field_behavior) = OUTPUT_ONLY];

  // Optional. Labels as key value pairs
  map<string, string> labels = 4 [(google.api.field_behavior) = OPTIONAL];

  // Optional. Display name of the Server
  string display_name = 5 [(google.api.field_behavior) = OPTIONAL];

  // Required. The access type of the Server.
  AccessType access_type = 6 [(google.api.field_behavior) = REQUIRED];

  // Output only. The state of the server.
  State state = 9 [(google.api.field_behavior) = OUTPUT_ONLY];

  // Output only. Credentials of the FTP Server.
  ServerCredential google_managed_server_credential = 10
      [(google.api.field_behavior) = OUTPUT_ONLY];

  // Output only. Service agent used to access the customer bucket.
  string service_agent = 11 [(google.api.field_behavior) = OUTPUT_ONLY];
}

// Message for requesting list of Servers
message ListServersRequest {
  // Required. Parent value for ListServersRequest
  string parent = 1 [
    (google.api.field_behavior) = REQUIRED,
    (google.api.resource_reference) = {
      child_type: "ftp.googleapis.com/Server"
    }
  ];

  // Optional. Requested page size. Server may return fewer items than
  // requested. If unspecified, server will pick an appropriate default.
  int32 page_size = 2 [(google.api.field_behavior) = OPTIONAL];

  // Optional. A token identifying a page of results the server should return.
  string page_token = 3 [(google.api.field_behavior) = OPTIONAL];

  // Optional. Filtering results
  string filter = 4 [(google.api.field_behavior) = OPTIONAL];

  // Optional. Hint for how to order the results
  string order_by = 5 [(google.api.field_behavior) = OPTIONAL];

  // Optional. The view of the Server resource to return.
  ServerView view = 6 [(google.api.field_behavior) = OPTIONAL];
}

// Message for response to listing Servers
message ListServersResponse {
  // The list of Server
  repeated Server servers = 1;

  // A token identifying a page of results the server should return.
  string next_page_token = 2;

  // Unordered list. Locations that could not be reached.
  repeated string unreachable = 3
      [(google.api.field_behavior) = UNORDERED_LIST];
}

// Message for getting a Server
message GetServerRequest {
  // Required. Name of the resource
  string name = 1 [
    (google.api.field_behavior) = REQUIRED,
    (google.api.resource_reference) = { type: "ftp.googleapis.com/Server" }
  ];

  // Optional. The view of the Server resource to return.
  ServerView view = 2 [(google.api.field_behavior) = OPTIONAL];
}

// Message for creating a Server
message CreateServerRequest {
  // Required. Value for parent.
  string parent = 1 [
    (google.api.field_behavior) = REQUIRED,
    (google.api.resource_reference) = {
      child_type: "ftp.googleapis.com/Server"
    }
  ];

  // Required. A unique ID for the server. Must start with a lowercase letter,
  // and end with a lowercase letter or number. Can contain lowercase letters,
  // numbers, and hyphens. Maximum length is 30 characters.
  string server_id = 2 [(google.api.field_behavior) = REQUIRED];

  // Required. The resource being created
  Server server = 3 [(google.api.field_behavior) = REQUIRED];

  // Optional. An optional request ID to identify requests. Specify a unique
  // request ID so that if you must retry your request, the server will know to
  // ignore the request if it has already been completed. The server will
  // guarantee that for at least 60 minutes since the first request.
  //
  // For example, consider a situation where you make an initial request and the
  // request times out. If you make the request again with the same request
  // ID, the server can check if original operation with the same request ID
  // was received, and if so, will ignore the second request. This prevents
  // clients from accidentally creating duplicate commitments.
  //
  // The request ID must be a valid UUID with the exception that zero UUID is
  // not supported (00000000-0000-0000-0000-000000000000).
  string request_id = 4 [
    (google.api.field_info).format = UUID4,
    (google.api.field_behavior) = OPTIONAL
  ];
}

// Message for updating a Server
message UpdateServerRequest {
  // Optional. Field mask is used to specify the fields to be overwritten in the
  // Server resource by the update.
  // The fields specified in the update_mask are relative to the resource, not
  // the full request. A field will be overwritten if it is in the mask. If the
  // user does not provide a mask then all fields present in the request will be
  // overwritten.
  google.protobuf.FieldMask update_mask = 1
      [(google.api.field_behavior) = OPTIONAL];

  // Required. The resource being updated
  Server server = 2 [(google.api.field_behavior) = REQUIRED];

  // Optional. An optional request ID to identify requests. Specify a unique
  // request ID so that if you must retry your request, the server will know to
  // ignore the request if it has already been completed. The server will
  // guarantee that for at least 60 minutes since the first request.
  //
  // For example, consider a situation where you make an initial request and the
  // request times out. If you make the request again with the same request
  // ID, the server can check if original operation with the same request ID
  // was received, and if so, will ignore the second request. This prevents
  // clients from accidentally creating duplicate commitments.
  //
  // The request ID must be a valid UUID with the exception that zero UUID is
  // not supported (00000000-0000-0000-0000-000000000000).
  string request_id = 3 [
    (google.api.field_info).format = UUID4,
    (google.api.field_behavior) = OPTIONAL
  ];
}

// Message for deleting a Server
// Note: Cascading delete is not supported. Any nested User resources
// under this Server must be deleted before the Server itself can be deleted.
// Attempting to delete a Server with active User resources will result in an
// error.
message DeleteServerRequest {
  // Required. Name of the resource
  string name = 1 [
    (google.api.field_behavior) = REQUIRED,
    (google.api.resource_reference) = { type: "ftp.googleapis.com/Server" }
  ];
}

// Mapping of backing Cloud Storage path to the directory where the user lands
// in the SFTP server. If directory is not specified, it'll default to '/'.
//
// Eg 1 -
// (bucket_name: bucket, bucket_prefix: path1/path2, directory:
// /abc/def/username)
//
// The user will land at /abcd/def/username, and the view there will match that
// of /bucket/path1/path2. The user will not be aware of Cloud Storage prefix
// '/bucket/path1' and there will be no such directory in the view.
//
// Eg 2 -
// (bucket_name: bucket, bucket_prefix: path1/path2, directory: '')
//
// The user will land at '/', and the view there will match
// that of /bucket/path1/path2. The user will not be aware of Cloud Storage
// prefix '/bucket/path1/path2' and there will be no such directory in the view.
message StorageDirectoryMapping {
  // Tracks read/write access to the bucket.
  enum Permission {
    // Permission unspecified.
    PERMISSION_UNSPECIFIED = 0;

    // Read only permission.
    READ_ONLY = 1;

    // Read write permission.
    READ_WRITE = 2;
  }

  // Required. Name of the bucket.
  string bucket = 1 [(google.api.field_behavior) = REQUIRED];

  // Optional. Prefix inside the bucket.
  string bucket_prefix = 2 [(google.api.field_behavior) = OPTIONAL];

  // Required. Directory where the user lands in the SFTP server.
  string directory = 3 [(google.api.field_behavior) = REQUIRED];

  // Required. Permission to the bucket.
  Permission permission = 4 [(google.api.field_behavior) = REQUIRED];
}

// Message describing User object
message User {
  option (google.api.resource) = {
    type: "ftp.googleapis.com/User"
    pattern: "projects/{project}/locations/{location}/servers/{server}/users/{user}"
    plural: "users"
    singular: "user"
  };

  // Tracks user creation.
  enum State {
    // State unspecified.
    STATE_UNSPECIFIED = 0;

    // User is being created.
    CREATING = 1;

    // User is ready to be used.
    ACTIVE = 2;

    // User creation failed.
    ERROR = 3;

    // The resource is being updated.
    UPDATING = 4;

    // The resource is being deleted.
    DELETING = 5;
  }

  // Identifier. User-friendly name via which User will be identified.
  // projects/{project}/locations/{location}/servers/{server}/users/{user}
  string name = 1 [(google.api.field_behavior) = IDENTIFIER];

  // Output only. [Output only] Create time stamp
  google.protobuf.Timestamp create_time = 2
      [(google.api.field_behavior) = OUTPUT_ONLY];

  // Output only. [Output only] Update time stamp
  google.protobuf.Timestamp update_time = 3
      [(google.api.field_behavior) = OUTPUT_ONLY];

  // Optional. Labels as key value pairs
  map<string, string> labels = 4 [(google.api.field_behavior) = OPTIONAL];

  // Output only. [Output only] The username of the user.
  string username = 5 [(google.api.field_behavior) = OUTPUT_ONLY];

  // Required. Service account in customer project attached to this SFTP User.
  string customer_service_account = 7 [(google.api.field_behavior) = REQUIRED];

  // Output only. Tracks user creation.
  State state = 8 [(google.api.field_behavior) = OUTPUT_ONLY];

  // Required. User credential for the user.
  // The maximum number of user credentials is 10.
  repeated UserCredential user_credentials = 9
      [(google.api.field_behavior) = REQUIRED];

  // Required. Mapping of Cloud Storage buckets to directories where the user
  // will land in the SFTP server.
  repeated StorageDirectoryMapping storage_directory_mappings = 10
      [(google.api.field_behavior) = REQUIRED];
}

// Message for requesting list of Users
message ListUsersRequest {
  // Required. Parent value for ListUsersRequest
  string parent = 1 [
    (google.api.field_behavior) = REQUIRED,
    (google.api.resource_reference) = { child_type: "ftp.googleapis.com/User" }
  ];

  // Optional. Requested page size. User may return fewer items than requested.
  // The maximum value is 1000; The default value is 50 if the field is omitted
  // (or set to 0).
  int32 page_size = 2 [(google.api.field_behavior) = OPTIONAL];

  // Optional. A token identifying a page of results the user should return.
  string page_token = 3 [(google.api.field_behavior) = OPTIONAL];

  // Optional. Filtering results
  string filter = 4 [(google.api.field_behavior) = OPTIONAL];

  // Optional. Hint for how to order the results
  string order_by = 5 [(google.api.field_behavior) = OPTIONAL];

  // Optional. The view of the User resource to return.
  UserView view = 6 [(google.api.field_behavior) = OPTIONAL];
}

// Message for response to listing Users
message ListUsersResponse {
  // The list of User
  repeated User users = 1;

  // A token identifying a page of results the user should return.
  string next_page_token = 2;

  // Unordered list. Locations that could not be reached.
  repeated string unreachable = 3
      [(google.api.field_behavior) = UNORDERED_LIST];
}

// Message for getting a User
message GetUserRequest {
  // Required. Name of the resource
  string name = 1 [
    (google.api.field_behavior) = REQUIRED,
    (google.api.resource_reference) = { type: "ftp.googleapis.com/User" }
  ];

  // Optional. The view of the User resource to return.
  UserView view = 2 [(google.api.field_behavior) = OPTIONAL];
}

// Message for creating a User
message CreateUserRequest {
  // Required. Value for parent.
  string parent = 1 [
    (google.api.field_behavior) = REQUIRED,
    (google.api.resource_reference) = { child_type: "ftp.googleapis.com/User" }
  ];

  // Required. A unique user ID for the SFTP user. The user ID must start with a
  // lowercase letter and can include lowercase letters, numbers, or hyphens.
  string user_id = 2 [(google.api.field_behavior) = REQUIRED];

  // Required. The resource being created
  User user = 3 [(google.api.field_behavior) = REQUIRED];

  // Optional. An optional request ID to identify requests. Specify a unique
  // request ID so that if you must retry your request, the server will know to
  // ignore the request if it has already been completed. The server will
  // guarantee that for at least 60 minutes since the first request.
  //
  // For example, consider a situation where you make an initial request and the
  // request times out. If you make the request again with the same request
  // ID, the server can check if original operation with the same request ID
  // was received, and if so, will ignore the second request. This prevents
  // clients from accidentally creating duplicate commitments.
  //
  // The request ID must be a valid UUID with the exception that zero UUID is
  // not supported (00000000-0000-0000-0000-000000000000).
  string request_id = 4 [
    (google.api.field_info).format = UUID4,
    (google.api.field_behavior) = OPTIONAL
  ];
}

// Message for updating a User
message UpdateUserRequest {
  // Optional. Field mask is used to specify the fields to be overwritten in the
  // User resource by the update.
  // The fields specified in the update_mask are relative to the resource, not
  // the full request. A field will be overwritten if it is in the mask. If the
  // user does not provide a mask then all fields present in the request will be
  // overwritten.
  google.protobuf.FieldMask update_mask = 1
      [(google.api.field_behavior) = OPTIONAL];

  // Required. The resource being updated
  User user = 2 [(google.api.field_behavior) = REQUIRED];
}

// Message for deleting a User
message DeleteUserRequest {
  // Required. Name of the resource
  string name = 1 [
    (google.api.field_behavior) = REQUIRED,
    (google.api.resource_reference) = { type: "ftp.googleapis.com/User" }
  ];

  // Optional. If set to true, the request will force the deletion of the User.
  bool force = 3 [(google.api.field_behavior) = OPTIONAL];
}

// Request message for starting a Server.
message StartServerRequest {
  // Required. Name of the resource
  // Format: `projects/{project}/locations/{location}/servers/{server}`
  string name = 1 [
    (google.api.field_behavior) = REQUIRED,
    (google.api.resource_reference) = { type: "ftp.googleapis.com/Server" }
  ];
}

// Request message for stopping a Server.
message StopServerRequest {
  // Required. Name of the resource.
  // Format: `projects/{project}/locations/{location}/servers/{server}`
  string name = 1 [
    (google.api.field_behavior) = REQUIRED,
    (google.api.resource_reference) = { type: "ftp.googleapis.com/Server" }
  ];
}

// Message describing UserCredential object
message UserCredential {
  // Type of credential.
  enum Type {
    // Type unspecified.
    TYPE_UNSPECIFIED = 0;

    // Public key credential.
    PUBLIC_KEY = 1;
  }

  // Required. Name of the user credential.
  string credential_name = 1 [(google.api.field_behavior) = REQUIRED];

  // Required. Type of credential.
  Type credential_type = 2 [(google.api.field_behavior) = REQUIRED];

  // Optional. SSH public key body in OpenSSH format.
  // Example: "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQ..."
  string ssh_public_key_body = 3 [(google.api.field_behavior) = OPTIONAL];
}

// Represents the metadata of the long-running operation.
message OperationMetadata {
  // Output only. The time the operation was created.
  google.protobuf.Timestamp create_time = 1
      [(google.api.field_behavior) = OUTPUT_ONLY];

  // Output only. The time the operation finished running.
  google.protobuf.Timestamp end_time = 2
      [(google.api.field_behavior) = OUTPUT_ONLY];

  // Output only. Server-defined resource path for the target of the operation.
  string target = 3 [(google.api.field_behavior) = OUTPUT_ONLY];

  // Output only. Name of the verb executed by the operation.
  string verb = 4 [(google.api.field_behavior) = OUTPUT_ONLY];

  // Output only. Human-readable status of the operation, if any.
  string status_message = 5 [(google.api.field_behavior) = OUTPUT_ONLY];

  // Output only. Identifies whether the user has requested cancellation
  // of the operation. Operations that have been cancelled successfully
  // have
  // [google.longrunning.Operation.error][google.longrunning.Operation.error]
  // value with a [google.rpc.Status.code][google.rpc.Status.code] of `1`,
  // corresponding to `Code.CANCELLED`.
  bool requested_cancellation = 6 [(google.api.field_behavior) = OUTPUT_ONLY];

  // Output only. API version used to start the operation.
  string api_version = 7 [(google.api.field_behavior) = OUTPUT_ONLY];
}
