// Copyright 2023 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.recaptchaenterprise.v1;

import "google/api/annotations.proto";
import "google/api/client.proto";
import "google/api/field_behavior.proto";
import "google/api/resource.proto";
import "google/protobuf/empty.proto";
import "google/protobuf/field_mask.proto";
import "google/protobuf/timestamp.proto";
import "google/rpc/status.proto";

option csharp_namespace = "Google.Cloud.RecaptchaEnterprise.V1";
option go_package = "cloud.google.com/go/recaptchaenterprise/v2/apiv1/recaptchaenterprisepb;recaptchaenterprisepb";
option java_multiple_files = true;
option java_outer_classname = "RecaptchaEnterpriseProto";
option java_package = "com.google.recaptchaenterprise.v1";
option objc_class_prefix = "GCRE";
option php_namespace = "Google\\Cloud\\RecaptchaEnterprise\\V1";
option ruby_package = "Google::Cloud::RecaptchaEnterprise::V1";

// Service to determine the likelihood an event is legitimate.
service RecaptchaEnterpriseService {
  option (google.api.default_host) = "recaptchaenterprise.googleapis.com";
  option (google.api.oauth_scopes) =
      "https://www.googleapis.com/auth/cloud-platform";

  // Creates an Assessment of the likelihood an event is legitimate.
  rpc CreateAssessment(CreateAssessmentRequest) returns (Assessment) {
    option (google.api.http) = {
      post: "/v1/{parent=projects/*}/assessments"
      body: "assessment"
    };
    option (google.api.method_signature) = "parent,assessment";
  }

  // Annotates a previously created Assessment to provide additional information
  // on whether the event turned out to be authentic or fraudulent.
  rpc AnnotateAssessment(AnnotateAssessmentRequest)
      returns (AnnotateAssessmentResponse) {
    option (google.api.http) = {
      post: "/v1/{name=projects/*/assessments/*}:annotate"
      body: "*"
    };
    option (google.api.method_signature) = "name,annotation";
  }

  // Creates a new reCAPTCHA Enterprise key.
  rpc CreateKey(CreateKeyRequest) returns (Key) {
    option (google.api.http) = {
      post: "/v1/{parent=projects/*}/keys"
      body: "key"
    };
    option (google.api.method_signature) = "parent,key";
  }

  // Returns the list of all keys that belong to a project.
  rpc ListKeys(ListKeysRequest) returns (ListKeysResponse) {
    option (google.api.http) = {
      get: "/v1/{parent=projects/*}/keys"
    };
    option (google.api.method_signature) = "parent";
  }

  // Returns the secret key related to the specified public key.
  // You must use the legacy secret key only in a 3rd party integration with
  // legacy reCAPTCHA.
  rpc RetrieveLegacySecretKey(RetrieveLegacySecretKeyRequest)
      returns (RetrieveLegacySecretKeyResponse) {
    option (google.api.http) = {
      get: "/v1/{key=projects/*/keys/*}:retrieveLegacySecretKey"
    };
    option (google.api.method_signature) = "key";
  }

  // Returns the specified key.
  rpc GetKey(GetKeyRequest) returns (Key) {
    option (google.api.http) = {
      get: "/v1/{name=projects/*/keys/*}"
    };
    option (google.api.method_signature) = "name";
  }

  // Updates the specified key.
  rpc UpdateKey(UpdateKeyRequest) returns (Key) {
    option (google.api.http) = {
      patch: "/v1/{key.name=projects/*/keys/*}"
      body: "key"
    };
    option (google.api.method_signature) = "key,update_mask";
  }

  // Deletes the specified key.
  rpc DeleteKey(DeleteKeyRequest) returns (google.protobuf.Empty) {
    option (google.api.http) = {
      delete: "/v1/{name=projects/*/keys/*}"
    };
    option (google.api.method_signature) = "name";
  }

  // Migrates an existing key from reCAPTCHA to reCAPTCHA Enterprise.
  // Once a key is migrated, it can be used from either product. SiteVerify
  // requests are billed as CreateAssessment calls. You must be
  // authenticated as one of the current owners of the reCAPTCHA Key, and
  // your user must have the reCAPTCHA Enterprise Admin IAM role in the
  // destination project.
  rpc MigrateKey(MigrateKeyRequest) returns (Key) {
    option (google.api.http) = {
      post: "/v1/{name=projects/*/keys/*}:migrate"
      body: "*"
    };
  }

  // Get some aggregated metrics for a Key. This data can be used to build
  // dashboards.
  rpc GetMetrics(GetMetricsRequest) returns (Metrics) {
    option (google.api.http) = {
      get: "/v1/{name=projects/*/keys/*/metrics}"
    };
    option (google.api.method_signature) = "name";
  }

  // Creates a new FirewallPolicy, specifying conditions at which reCAPTCHA
  // Enterprise actions can be executed.
  // A project may have a maximum of 1000 policies.
  rpc CreateFirewallPolicy(CreateFirewallPolicyRequest)
      returns (FirewallPolicy) {
    option (google.api.http) = {
      post: "/v1/{parent=projects/*}/firewallpolicies"
      body: "firewall_policy"
    };
    option (google.api.method_signature) = "parent,firewall_policy";
  }

  // Returns the list of all firewall policies that belong to a project.
  rpc ListFirewallPolicies(ListFirewallPoliciesRequest)
      returns (ListFirewallPoliciesResponse) {
    option (google.api.http) = {
      get: "/v1/{parent=projects/*}/firewallpolicies"
    };
    option (google.api.method_signature) = "parent";
  }

  // Returns the specified firewall policy.
  rpc GetFirewallPolicy(GetFirewallPolicyRequest) returns (FirewallPolicy) {
    option (google.api.http) = {
      get: "/v1/{name=projects/*/firewallpolicies/*}"
    };
    option (google.api.method_signature) = "name";
  }

  // Updates the specified firewall policy.
  rpc UpdateFirewallPolicy(UpdateFirewallPolicyRequest)
      returns (FirewallPolicy) {
    option (google.api.http) = {
      patch: "/v1/{firewall_policy.name=projects/*/firewallpolicies/*}"
      body: "firewall_policy"
    };
    option (google.api.method_signature) = "firewall_policy,update_mask";
  }

  // Deletes the specified firewall policy.
  rpc DeleteFirewallPolicy(DeleteFirewallPolicyRequest)
      returns (google.protobuf.Empty) {
    option (google.api.http) = {
      delete: "/v1/{name=projects/*/firewallpolicies/*}"
    };
    option (google.api.method_signature) = "name";
  }

  // List groups of related accounts.
  rpc ListRelatedAccountGroups(ListRelatedAccountGroupsRequest)
      returns (ListRelatedAccountGroupsResponse) {
    option (google.api.http) = {
      get: "/v1/{parent=projects/*}/relatedaccountgroups"
    };
    option (google.api.method_signature) = "parent";
  }

  // Get memberships in a group of related accounts.
  rpc ListRelatedAccountGroupMemberships(
      ListRelatedAccountGroupMembershipsRequest)
      returns (ListRelatedAccountGroupMembershipsResponse) {
    option (google.api.http) = {
      get: "/v1/{parent=projects/*/relatedaccountgroups/*}/memberships"
    };
    option (google.api.method_signature) = "parent";
  }

  // Search group memberships related to a given account.
  rpc SearchRelatedAccountGroupMemberships(
      SearchRelatedAccountGroupMembershipsRequest)
      returns (SearchRelatedAccountGroupMembershipsResponse) {
    option (google.api.http) = {
      post: "/v1/{project=projects/*}/relatedaccountgroupmemberships:search"
      body: "*"
    };
    option (google.api.method_signature) = "project,hashed_account_id";
  }
}

// The create assessment request message.
message CreateAssessmentRequest {
  // Required. The name of the project in which the assessment will be created,
  // in the format `projects/{project}`.
  string parent = 1 [
    (google.api.field_behavior) = REQUIRED,
    (google.api.resource_reference) = {
      type: "cloudresourcemanager.googleapis.com/Project"
    }
  ];

  // Required. The assessment details.
  Assessment assessment = 2 [(google.api.field_behavior) = REQUIRED];
}

// Describes an event in the lifecycle of a payment transaction.
message TransactionEvent {
  // Enum that represents an event in the payment transaction lifecycle.
  enum TransactionEventType {
    // Default, unspecified event type.
    TRANSACTION_EVENT_TYPE_UNSPECIFIED = 0;

    // Indicates that the transaction is approved by the merchant. The
    // accompanying reasons can include terms such as 'INHOUSE', 'ACCERTIFY',
    // 'CYBERSOURCE', or 'MANUAL_REVIEW'.
    MERCHANT_APPROVE = 1;

    // Indicates that the transaction is denied and concluded due to risks
    // detected by the merchant. The accompanying reasons can include terms such
    // as 'INHOUSE',  'ACCERTIFY',  'CYBERSOURCE', or 'MANUAL_REVIEW'.
    MERCHANT_DENY = 2;

    // Indicates that the transaction is being evaluated by a human, due to
    // suspicion or risk.
    MANUAL_REVIEW = 3;

    // Indicates that the authorization attempt with the card issuer succeeded.
    AUTHORIZATION = 4;

    // Indicates that the authorization attempt with the card issuer failed.
    // The accompanying reasons can include Visa's '54' indicating that the card
    // is expired, or '82' indicating that the CVV is incorrect.
    AUTHORIZATION_DECLINE = 5;

    // Indicates that the transaction is completed because the funds were
    // settled.
    PAYMENT_CAPTURE = 6;

    // Indicates that the transaction could not be completed because the funds
    // were not settled.
    PAYMENT_CAPTURE_DECLINE = 7;

    // Indicates that the transaction has been canceled. Specify the reason
    // for the cancellation. For example, 'INSUFFICIENT_INVENTORY'.
    CANCEL = 8;

    // Indicates that the merchant has received a chargeback inquiry due to
    // fraud for the transaction, requesting additional information before a
    // fraud chargeback is officially issued and a formal chargeback
    // notification is sent.
    CHARGEBACK_INQUIRY = 9;

    // Indicates that the merchant has received a chargeback alert due to fraud
    // for the transaction. The process of resolving the dispute without
    // involving the payment network is started.
    CHARGEBACK_ALERT = 10;

    // Indicates that a fraud notification is issued for the transaction, sent
    // by the payment instrument's issuing bank because the transaction appears
    // to be fraudulent. We recommend including TC40 or SAFE data in the
    // `reason` field for this event type. For partial chargebacks, we recommend
    // that you include an amount in the `value` field.
    FRAUD_NOTIFICATION = 11;

    // Indicates that the merchant is informed by the payment network that the
    // transaction has entered the chargeback process due to fraud. Reason code
    // examples include Discover's '6005' and '6041'. For partial chargebacks,
    // we recommend that you include an amount in the `value` field.
    CHARGEBACK = 12;

    // Indicates that the transaction has entered the chargeback process due to
    // fraud, and that the merchant has chosen to enter representment. Reason
    // examples include Discover's '6005' and '6041'. For partial chargebacks,
    // we recommend that you include an amount in the `value` field.
    CHARGEBACK_REPRESENTMENT = 13;

    // Indicates that the transaction has had a fraud chargeback which was
    // illegitimate and was reversed as a result. For partial chargebacks, we
    // recommend that you include an amount in the `value` field.
    CHARGEBACK_REVERSE = 14;

    // Indicates that the merchant has received a refund for a completed
    // transaction. For partial refunds, we recommend that you include an amount
    // in the `value` field. Reason example: 'TAX_EXEMPT' (partial refund of
    // exempt tax)
    REFUND_REQUEST = 15;

    // Indicates that the merchant has received a refund request for this
    // transaction, but that they have declined it. For partial refunds, we
    // recommend that you include an amount in the `value` field. Reason
    // example: 'TAX_EXEMPT' (partial refund of exempt tax)
    REFUND_DECLINE = 16;

    // Indicates that the completed transaction was refunded by the merchant.
    // For partial refunds, we recommend that you include an amount in the
    // `value` field. Reason example: 'TAX_EXEMPT' (partial refund of exempt
    // tax)
    REFUND = 17;

    // Indicates that the completed transaction was refunded by the merchant,
    // and that this refund was reversed. For partial refunds, we recommend that
    // you include an amount in the `value` field.
    REFUND_REVERSE = 18;
  }

  // Optional. The type of this transaction event.
  TransactionEventType event_type = 1 [(google.api.field_behavior) = OPTIONAL];

  // Optional. The reason or standardized code that corresponds with this
  // transaction event, if one exists. For example, a CHARGEBACK event with code
  // 6005.
  string reason = 2 [(google.api.field_behavior) = OPTIONAL];

  // Optional. The value that corresponds with this transaction event, if one
  // exists. For example, a refund event where $5.00 was refunded. Currency is
  // obtained from the original transaction data.
  double value = 3 [(google.api.field_behavior) = OPTIONAL];

  // Optional. Timestamp when this transaction event occurred; otherwise assumed
  // to be the time of the API call.
  google.protobuf.Timestamp event_time = 4
      [(google.api.field_behavior) = OPTIONAL];
}

// The request message to annotate an Assessment.
message AnnotateAssessmentRequest {
  // Enum that represents the types of annotations.
  enum Annotation {
    // Default unspecified type.
    ANNOTATION_UNSPECIFIED = 0;

    // Provides information that the event turned out to be legitimate.
    LEGITIMATE = 1;

    // Provides information that the event turned out to be fraudulent.
    FRAUDULENT = 2;

    // Provides information that the event was related to a login event in which
    // the user typed the correct password. Deprecated, prefer indicating
    // CORRECT_PASSWORD through the reasons field instead.
    PASSWORD_CORRECT = 3 [deprecated = true];

    // Provides information that the event was related to a login event in which
    // the user typed the incorrect password. Deprecated, prefer indicating
    // INCORRECT_PASSWORD through the reasons field instead.
    PASSWORD_INCORRECT = 4 [deprecated = true];
  }

  // Enum that represents potential reasons for annotating an assessment.
  enum Reason {
    // Default unspecified reason.
    REASON_UNSPECIFIED = 0;

    // Indicates that the transaction had a chargeback issued with no other
    // details. When possible, specify the type by using CHARGEBACK_FRAUD or
    // CHARGEBACK_DISPUTE instead.
    CHARGEBACK = 1;

    // Indicates that the transaction had a chargeback issued related to an
    // alleged unauthorized transaction from the cardholder's perspective (for
    // example, the card number was stolen).
    CHARGEBACK_FRAUD = 8;

    // Indicates that the transaction had a chargeback issued related to the
    // cardholder having provided their card details but allegedly not being
    // satisfied with the purchase (for example, misrepresentation, attempted
    // cancellation).
    CHARGEBACK_DISPUTE = 9;

    // Indicates that the completed payment transaction was refunded by the
    // seller.
    REFUND = 10;

    // Indicates that the completed payment transaction was determined to be
    // fraudulent by the seller, and was cancelled and refunded as a result.
    REFUND_FRAUD = 11;

    // Indicates that the payment transaction was accepted, and the user was
    // charged.
    TRANSACTION_ACCEPTED = 12;

    // Indicates that the payment transaction was declined, for example due to
    // invalid card details.
    TRANSACTION_DECLINED = 13;

    // Indicates the transaction associated with the assessment is suspected of
    // being fraudulent based on the payment method, billing details, shipping
    // address or other transaction information.
    PAYMENT_HEURISTICS = 2;

    // Indicates that the user was served a 2FA challenge. An old assessment
    // with `ENUM_VALUES.INITIATED_TWO_FACTOR` reason that has not been
    // overwritten with `PASSED_TWO_FACTOR` is treated as an abandoned 2FA flow.
    // This is equivalent to `FAILED_TWO_FACTOR`.
    INITIATED_TWO_FACTOR = 7;

    // Indicates that the user passed a 2FA challenge.
    PASSED_TWO_FACTOR = 3;

    // Indicates that the user failed a 2FA challenge.
    FAILED_TWO_FACTOR = 4;

    // Indicates the user provided the correct password.
    CORRECT_PASSWORD = 5;

    // Indicates the user provided an incorrect password.
    INCORRECT_PASSWORD = 6;

    // Indicates that the user sent unwanted and abusive messages to other users
    // of the platform, such as spam, scams, phishing, or social engineering.
    SOCIAL_SPAM = 14;
  }

  // Required. The resource name of the Assessment, in the format
  // `projects/{project}/assessments/{assessment}`.
  string name = 1 [
    (google.api.field_behavior) = REQUIRED,
    (google.api.resource_reference) = {
      type: "recaptchaenterprise.googleapis.com/Assessment"
    }
  ];

  // Optional. The annotation that will be assigned to the Event. This field can
  // be left empty to provide reasons that apply to an event without concluding
  // whether the event is legitimate or fraudulent.
  Annotation annotation = 2 [(google.api.field_behavior) = OPTIONAL];

  // Optional. Reasons for the annotation that are assigned to the event.
  repeated Reason reasons = 3 [(google.api.field_behavior) = OPTIONAL];

  // Optional. A stable account identifier to apply to the assessment. This is
  // an alternative to setting `account_id` in `CreateAssessment`, for example
  // when a stable account identifier is not yet known in the initial request.
  string account_id = 7 [(google.api.field_behavior) = OPTIONAL];

  // Optional. A stable hashed account identifier to apply to the assessment.
  // This is an alternative to setting `hashed_account_id` in
  // `CreateAssessment`, for example when a stable account identifier is not yet
  // known in the initial request.
  bytes hashed_account_id = 4 [(google.api.field_behavior) = OPTIONAL];

  // Optional. If the assessment is part of a payment transaction, provide
  // details on payment lifecycle events that occur in the transaction.
  TransactionEvent transaction_event = 5
      [(google.api.field_behavior) = OPTIONAL];
}

// Empty response for AnnotateAssessment.
message AnnotateAssessmentResponse {}

// Information about a verification endpoint that can be used for 2FA.
message EndpointVerificationInfo {
  oneof endpoint {
    // Email address for which to trigger a verification request.
    string email_address = 1;

    // Phone number for which to trigger a verification request. Should be given
    // in E.164 format.
    string phone_number = 2;
  }

  // Output only. Token to provide to the client to trigger endpoint
  // verification. It must be used within 15 minutes.
  string request_token = 3 [(google.api.field_behavior) = OUTPUT_ONLY];

  // Output only. Timestamp of the last successful verification for the
  // endpoint, if any.
  google.protobuf.Timestamp last_verification_time = 4
      [(google.api.field_behavior) = OUTPUT_ONLY];
}

// Information about account verification, used for identity verification.
message AccountVerificationInfo {
  // Result of the account verification as contained in the verdict token issued
  // at the end of the verification flow.
  enum Result {
    // No information about the latest account verification.
    RESULT_UNSPECIFIED = 0;

    // The user was successfully verified. This means the account verification
    // challenge was successfully completed.
    SUCCESS_USER_VERIFIED = 1;

    // The user failed the verification challenge.
    ERROR_USER_NOT_VERIFIED = 2;

    // The site is not properly onboarded to use the account verification
    // feature.
    ERROR_SITE_ONBOARDING_INCOMPLETE = 3;

    // The recipient is not allowed for account verification. This can occur
    // during integration but should not occur in production.
    ERROR_RECIPIENT_NOT_ALLOWED = 4;

    // The recipient has already been sent too many verification codes in a
    // short amount of time.
    ERROR_RECIPIENT_ABUSE_LIMIT_EXHAUSTED = 5;

    // The verification flow could not be completed due to a critical internal
    // error.
    ERROR_CRITICAL_INTERNAL = 6;

    // The client has exceeded their two factor request quota for this period of
    // time.
    ERROR_CUSTOMER_QUOTA_EXHAUSTED = 7;

    // The request cannot be processed at the time because of an incident. This
    // bypass can be restricted to a problematic destination email domain, a
    // customer, or could affect the entire service.
    ERROR_VERIFICATION_BYPASSED = 8;

    // The request parameters do not match with the token provided and cannot be
    // processed.
    ERROR_VERDICT_MISMATCH = 9;
  }

  // Optional. Endpoints that can be used for identity verification.
  repeated EndpointVerificationInfo endpoints = 1
      [(google.api.field_behavior) = OPTIONAL];

  // Optional. Language code preference for the verification message, set as a
  // IETF BCP 47 language code.
  string language_code = 3 [(google.api.field_behavior) = OPTIONAL];

  // Output only. Result of the latest account verification challenge.
  Result latest_verification_result = 7
      [(google.api.field_behavior) = OUTPUT_ONLY];

  // Username of the account that is being verified. Deprecated. Customers
  // should now provide the hashed account ID field in Event.
  string username = 2 [deprecated = true];
}

// Private password leak verification info.
message PrivatePasswordLeakVerification {
  // Required. Exactly 26-bit prefix of the SHA-256 hash of the canonicalized
  // username. It is used to look up password leaks associated with that hash
  // prefix.
  bytes lookup_hash_prefix = 1 [(google.api.field_behavior) = REQUIRED];

  // Optional. Encrypted Scrypt hash of the canonicalized username+password. It
  // is re-encrypted by the server and returned through
  // `reencrypted_user_credentials_hash`.
  bytes encrypted_user_credentials_hash = 2
      [(google.api.field_behavior) = OPTIONAL];

  // Output only. List of prefixes of the encrypted potential password leaks
  // that matched the given parameters. They must be compared with the
  // client-side decryption prefix of `reencrypted_user_credentials_hash`
  repeated bytes encrypted_leak_match_prefixes = 3
      [(google.api.field_behavior) = OUTPUT_ONLY];

  // Output only. Corresponds to the re-encryption of the
  // `encrypted_user_credentials_hash` field. It is used to match potential
  // password leaks within `encrypted_leak_match_prefixes`.
  bytes reencrypted_user_credentials_hash = 4
      [(google.api.field_behavior) = OUTPUT_ONLY];
}

// A reCAPTCHA Enterprise assessment resource.
message Assessment {
  option (google.api.resource) = {
    type: "recaptchaenterprise.googleapis.com/Assessment"
    pattern: "projects/{project}/assessments/{assessment}"
  };

  // Output only. Identifier. The resource name for the Assessment in the format
  // `projects/{project}/assessments/{assessment}`.
  string name = 1 [
    (google.api.field_behavior) = OUTPUT_ONLY,
    (google.api.field_behavior) = IDENTIFIER
  ];

  // Optional. The event being assessed.
  Event event = 2 [(google.api.field_behavior) = OPTIONAL];

  // Output only. The risk analysis result for the event being assessed.
  RiskAnalysis risk_analysis = 3 [(google.api.field_behavior) = OUTPUT_ONLY];

  // Output only. Properties of the provided event token.
  TokenProperties token_properties = 4
      [(google.api.field_behavior) = OUTPUT_ONLY];

  // Optional. Account verification information for identity verification. The
  // assessment event must include a token and site key to use this feature.
  AccountVerificationInfo account_verification = 5
      [(google.api.field_behavior) = OPTIONAL];

  // Output only. Assessment returned by account defender when an account
  // identifier is provided.
  AccountDefenderAssessment account_defender_assessment = 6
      [(google.api.field_behavior) = OUTPUT_ONLY];

  // Optional. The private password leak verification field contains the
  // parameters that are used to to check for leaks privately without sharing
  // user credentials.
  PrivatePasswordLeakVerification private_password_leak_verification = 8
      [(google.api.field_behavior) = OPTIONAL];

  // Output only. Assessment returned when firewall policies belonging to the
  // project are evaluated using the field firewall_policy_evaluation.
  FirewallPolicyAssessment firewall_policy_assessment = 10
      [(google.api.field_behavior) = OUTPUT_ONLY];

  // Output only. Assessment returned by Fraud Prevention when TransactionData
  // is provided.
  FraudPreventionAssessment fraud_prevention_assessment = 11
      [(google.api.field_behavior) = OUTPUT_ONLY];

  // Output only. Fraud Signals specific to the users involved in a payment
  // transaction.
  FraudSignals fraud_signals = 13 [(google.api.field_behavior) = OUTPUT_ONLY];
}

// The event being assessed.
message Event {
  // Optional. The user response token provided by the reCAPTCHA Enterprise
  // client-side integration on your site.
  string token = 1 [(google.api.field_behavior) = OPTIONAL];

  // Optional. The site key that was used to invoke reCAPTCHA Enterprise on your
  // site and generate the token.
  string site_key = 2 [(google.api.field_behavior) = OPTIONAL];

  // Optional. The user agent present in the request from the user's device
  // related to this event.
  string user_agent = 3 [(google.api.field_behavior) = OPTIONAL];

  // Optional. The IP address in the request from the user's device related to
  // this event.
  string user_ip_address = 4 [(google.api.field_behavior) = OPTIONAL];

  // Optional. The expected action for this type of event. This should be the
  // same action provided at token generation time on client-side platforms
  // already integrated with recaptcha enterprise.
  string expected_action = 5 [(google.api.field_behavior) = OPTIONAL];

  // Optional. Deprecated: use `user_info.account_id` instead.
  // Unique stable hashed user identifier for the request. The identifier must
  // be hashed using hmac-sha256 with stable secret.
  bytes hashed_account_id = 6
      [deprecated = true, (google.api.field_behavior) = OPTIONAL];

  // Optional. Flag for a reCAPTCHA express request for an assessment without a
  // token. If enabled, `site_key` must reference a SCORE key with WAF feature
  // set to EXPRESS.
  bool express = 14 [(google.api.field_behavior) = OPTIONAL];

  // Optional. The URI resource the user requested that triggered an assessment.
  string requested_uri = 8 [(google.api.field_behavior) = OPTIONAL];

  // Optional. Flag for running WAF token assessment.
  // If enabled, the token must be specified, and have been created by a
  // WAF-enabled key.
  bool waf_token_assessment = 9 [(google.api.field_behavior) = OPTIONAL];

  // Optional. JA3 fingerprint for SSL clients.
  string ja3 = 10 [(google.api.field_behavior) = OPTIONAL];

  // Optional. HTTP header information about the request.
  repeated string headers = 11 [(google.api.field_behavior) = OPTIONAL];

  // Optional. Flag for enabling firewall policy config assessment.
  // If this flag is enabled, the firewall policy will be evaluated and a
  // suggested firewall action will be returned in the response.
  bool firewall_policy_evaluation = 12 [(google.api.field_behavior) = OPTIONAL];

  // Optional. Data describing a payment transaction to be assessed. Sending
  // this data enables reCAPTCHA Enterprise Fraud Prevention and the
  // FraudPreventionAssessment component in the response.
  TransactionData transaction_data = 13
      [(google.api.field_behavior) = OPTIONAL];

  // Optional. Information about the user that generates this event, when they
  // can be identified. They are often identified through the use of an account
  // for logged-in requests or login/registration requests, or by providing user
  // identifiers for guest actions like checkout.
  UserInfo user_info = 15 [(google.api.field_behavior) = OPTIONAL];
}

// Transaction data associated with a payment protected by reCAPTCHA Enterprise.
message TransactionData {
  // Structured address format for billing and shipping addresses.
  message Address {
    // Optional. The recipient name, potentially including information such as
    // "care of".
    string recipient = 1 [(google.api.field_behavior) = OPTIONAL];

    // Optional. The first lines of the address. The first line generally
    // contains the street name and number, and further lines may include
    // information such as an apartment number.
    repeated string address = 2 [(google.api.field_behavior) = OPTIONAL];

    // Optional. The town/city of the address.
    string locality = 3 [(google.api.field_behavior) = OPTIONAL];

    // Optional. The state, province, or otherwise administrative area of the
    // address.
    string administrative_area = 4 [(google.api.field_behavior) = OPTIONAL];

    // Optional. The CLDR country/region of the address.
    string region_code = 5 [(google.api.field_behavior) = OPTIONAL];

    // Optional. The postal or ZIP code of the address.
    string postal_code = 6 [(google.api.field_behavior) = OPTIONAL];
  }

  // Details about a user's account involved in the transaction.
  message User {
    // Optional. Unique account identifier for this user. If using account
    // defender, this should match the hashed_account_id field. Otherwise, a
    // unique and persistent identifier for this account.
    string account_id = 6 [(google.api.field_behavior) = OPTIONAL];

    // Optional. The epoch milliseconds of the user's account creation.
    int64 creation_ms = 1 [(google.api.field_behavior) = OPTIONAL];

    // Optional. The email address of the user.
    string email = 2 [(google.api.field_behavior) = OPTIONAL];

    // Optional. Whether the email has been verified to be accessible by the
    // user (OTP or similar).
    bool email_verified = 3 [(google.api.field_behavior) = OPTIONAL];

    // Optional. The phone number of the user, with country code.
    string phone_number = 4 [(google.api.field_behavior) = OPTIONAL];

    // Optional. Whether the phone number has been verified to be accessible by
    // the user (OTP or similar).
    bool phone_verified = 5 [(google.api.field_behavior) = OPTIONAL];
  }

  // Line items being purchased in this transaction.
  message Item {
    // Optional. The full name of the item.
    string name = 1 [(google.api.field_behavior) = OPTIONAL];

    // Optional. The value per item that the user is paying, in the transaction
    // currency, after discounts.
    double value = 2 [(google.api.field_behavior) = OPTIONAL];

    // Optional. The quantity of this item that is being purchased.
    int64 quantity = 3 [(google.api.field_behavior) = OPTIONAL];

    // Optional. When a merchant is specified, its corresponding account_id.
    // Necessary to populate marketplace-style transactions.
    string merchant_account_id = 4 [(google.api.field_behavior) = OPTIONAL];
  }

  // Details about the transaction from the gateway.
  message GatewayInfo {
    // Optional. Name of the gateway service (for example, stripe, square,
    // paypal).
    string name = 1 [(google.api.field_behavior) = OPTIONAL];

    // Optional. Gateway response code describing the state of the transaction.
    string gateway_response_code = 2 [(google.api.field_behavior) = OPTIONAL];

    // Optional. AVS response code from the gateway
    // (available only when reCAPTCHA Enterprise is called after authorization).
    string avs_response_code = 3 [(google.api.field_behavior) = OPTIONAL];

    // Optional. CVV response code from the gateway
    // (available only when reCAPTCHA Enterprise is called after authorization).
    string cvv_response_code = 4 [(google.api.field_behavior) = OPTIONAL];
  }

  // Unique identifier for the transaction. This custom identifier can be used
  // to reference this transaction in the future, for example, labeling a refund
  // or chargeback event. Two attempts at the same transaction should use the
  // same transaction id.
  optional string transaction_id = 11;

  // Optional. The payment method for the transaction. The allowed values are:
  //
  // * credit-card
  // * debit-card
  // * gift-card
  // * processor-{name} (If a third-party is used, for example,
  // processor-paypal)
  // * custom-{name} (If an alternative method is used, for example,
  // custom-crypto)
  string payment_method = 1 [(google.api.field_behavior) = OPTIONAL];

  // Optional. The Bank Identification Number - generally the first 6 or 8
  // digits of the card.
  string card_bin = 2 [(google.api.field_behavior) = OPTIONAL];

  // Optional. The last four digits of the card.
  string card_last_four = 3 [(google.api.field_behavior) = OPTIONAL];

  // Optional. The currency code in ISO-4217 format.
  string currency_code = 4 [(google.api.field_behavior) = OPTIONAL];

  // Optional. The decimal value of the transaction in the specified currency.
  double value = 5 [(google.api.field_behavior) = OPTIONAL];

  // Optional. The value of shipping in the specified currency. 0 for free or no
  // shipping.
  double shipping_value = 12 [(google.api.field_behavior) = OPTIONAL];

  // Optional. Destination address if this transaction involves shipping a
  // physical item.
  Address shipping_address = 6 [(google.api.field_behavior) = OPTIONAL];

  // Optional. Address associated with the payment method when applicable.
  Address billing_address = 7 [(google.api.field_behavior) = OPTIONAL];

  // Optional. Information about the user paying/initiating the transaction.
  User user = 8 [(google.api.field_behavior) = OPTIONAL];

  // Optional. Information about the user or users fulfilling the transaction.
  repeated User merchants = 13 [(google.api.field_behavior) = OPTIONAL];

  // Optional. Items purchased in this transaction.
  repeated Item items = 14 [(google.api.field_behavior) = OPTIONAL];

  // Optional. Information about the payment gateway's response to the
  // transaction.
  GatewayInfo gateway_info = 10 [(google.api.field_behavior) = OPTIONAL];
}

// User information associated with a request protected by reCAPTCHA Enterprise.
message UserInfo {
  // Optional. Creation time for this account associated with this user. Leave
  // blank for non logged-in actions, guest checkout, or when there is no
  // account associated with the current user.
  google.protobuf.Timestamp create_account_time = 1
      [(google.api.field_behavior) = OPTIONAL];

  // Optional. For logged-in requests or login/registration requests, the unique
  // account identifier associated with this user. You can use the username if
  // it is stable (meaning it is the same for every request associated with the
  // same user), or any stable user ID of your choice. Leave blank for non
  // logged-in actions or guest checkout.
  string account_id = 2 [(google.api.field_behavior) = OPTIONAL];

  // Optional. Identifiers associated with this user or request.
  repeated UserId user_ids = 3 [(google.api.field_behavior) = OPTIONAL];
}

// An identifier associated with a user.
message UserId {
  oneof id_oneof {
    // Optional. An email address.
    string email = 1 [(google.api.field_behavior) = OPTIONAL];

    // Optional. A phone number. Should use the E.164 format.
    string phone_number = 2 [(google.api.field_behavior) = OPTIONAL];

    // Optional. A unique username, if different from all the other identifiers
    // and `account_id` that are provided. Can be a unique login handle or
    // display name for a user.
    string username = 3 [(google.api.field_behavior) = OPTIONAL];
  }
}

// Risk analysis result for an event.
message RiskAnalysis {
  // Reasons contributing to the risk analysis verdict.
  enum ClassificationReason {
    // Default unspecified type.
    CLASSIFICATION_REASON_UNSPECIFIED = 0;

    // Interactions matched the behavior of an automated agent.
    AUTOMATION = 1;

    // The event originated from an illegitimate environment.
    UNEXPECTED_ENVIRONMENT = 2;

    // Traffic volume from the event source is higher than normal.
    TOO_MUCH_TRAFFIC = 3;

    // Interactions with the site were significantly different than expected
    // patterns.
    UNEXPECTED_USAGE_PATTERNS = 4;

    // Too little traffic has been received from this site thus far to generate
    // quality risk analysis.
    LOW_CONFIDENCE_SCORE = 5;

    // The request matches behavioral characteristics of a carding attack.
    SUSPECTED_CARDING = 6;

    // The request matches behavioral characteristics of chargebacks for fraud.
    SUSPECTED_CHARGEBACK = 7;
  }

  // Output only. Legitimate event score from 0.0 to 1.0.
  // (1.0 means very likely legitimate traffic while 0.0 means very likely
  // non-legitimate traffic).
  float score = 1 [(google.api.field_behavior) = OUTPUT_ONLY];

  // Output only. Reasons contributing to the risk analysis verdict.
  repeated ClassificationReason reasons = 2
      [(google.api.field_behavior) = OUTPUT_ONLY];

  // Output only. Extended verdict reasons to be used for experimentation only.
  // The set of possible reasons is subject to change.
  repeated string extended_verdict_reasons = 3
      [(google.api.field_behavior) = OUTPUT_ONLY];
}

// Properties of the provided event token.
message TokenProperties {
  // Enum that represents the types of invalid token reasons.
  enum InvalidReason {
    // Default unspecified type.
    INVALID_REASON_UNSPECIFIED = 0;

    // If the failure reason was not accounted for.
    UNKNOWN_INVALID_REASON = 1;

    // The provided user verification token was malformed.
    MALFORMED = 2;

    // The user verification token had expired.
    EXPIRED = 3;

    // The user verification had already been seen.
    DUPE = 4;

    // The user verification token was not present.
    MISSING = 5;

    // A retriable error (such as network failure) occurred on the browser.
    // Could easily be simulated by an attacker.
    BROWSER_ERROR = 6;
  }

  // Output only. Whether the provided user response token is valid. When valid
  // = false, the reason could be specified in invalid_reason or it could also
  // be due to a user failing to solve a challenge or a sitekey mismatch (i.e
  // the sitekey used to generate the token was different than the one specified
  // in the assessment).
  bool valid = 1 [(google.api.field_behavior) = OUTPUT_ONLY];

  // Output only. Reason associated with the response when valid = false.
  InvalidReason invalid_reason = 2 [(google.api.field_behavior) = OUTPUT_ONLY];

  // Output only. The timestamp corresponding to the generation of the token.
  google.protobuf.Timestamp create_time = 3
      [(google.api.field_behavior) = OUTPUT_ONLY];

  // Output only. The hostname of the page on which the token was generated (Web
  // keys only).
  string hostname = 4 [(google.api.field_behavior) = OUTPUT_ONLY];

  // Output only. The name of the Android package with which the token was
  // generated (Android keys only).
  string android_package_name = 8 [(google.api.field_behavior) = OUTPUT_ONLY];

  // Output only. The ID of the iOS bundle with which the token was generated
  // (iOS keys only).
  string ios_bundle_id = 9 [(google.api.field_behavior) = OUTPUT_ONLY];

  // Output only. Action name provided at token generation.
  string action = 5 [(google.api.field_behavior) = OUTPUT_ONLY];
}

// Assessment for Fraud Prevention.
message FraudPreventionAssessment {
  // Information about stolen instrument fraud, where the user is not the
  // legitimate owner of the instrument being used for the purchase.
  message StolenInstrumentVerdict {
    // Output only. Probability of this transaction being executed with a stolen
    // instrument. Values are from 0.0 (lowest) to 1.0 (highest).
    float risk = 1 [(google.api.field_behavior) = OUTPUT_ONLY];
  }

  // Information about card testing fraud, where an adversary is testing
  // fraudulently obtained cards or brute forcing their details.
  message CardTestingVerdict {
    // Output only. Probability of this transaction attempt being part of a card
    // testing attack. Values are from 0.0 (lowest) to 1.0 (highest).
    float risk = 1 [(google.api.field_behavior) = OUTPUT_ONLY];
  }

  // Information about behavioral trust of the transaction.
  message BehavioralTrustVerdict {
    // Output only. Probability of this transaction attempt being executed in a
    // behaviorally trustworthy way. Values are from 0.0 (lowest) to 1.0
    // (highest).
    float trust = 1 [(google.api.field_behavior) = OUTPUT_ONLY];
  }

  // Output only. Probability of this transaction being fraudulent. Summarizes
  // the combined risk of attack vectors below. Values are from 0.0 (lowest)
  // to 1.0 (highest).
  float transaction_risk = 1 [(google.api.field_behavior) = OUTPUT_ONLY];

  // Output only. Assessment of this transaction for risk of a stolen
  // instrument.
  StolenInstrumentVerdict stolen_instrument_verdict = 2
      [(google.api.field_behavior) = OUTPUT_ONLY];

  // Output only. Assessment of this transaction for risk of being part of a
  // card testing attack.
  CardTestingVerdict card_testing_verdict = 3
      [(google.api.field_behavior) = OUTPUT_ONLY];

  // Output only. Assessment of this transaction for behavioral trust.
  BehavioralTrustVerdict behavioral_trust_verdict = 4
      [(google.api.field_behavior) = OUTPUT_ONLY];
}

// Fraud signals describing users and cards involved in the transaction.
message FraudSignals {
  // Signals describing the user involved in this transaction.
  message UserSignals {
    // Output only. This user (based on email, phone, and other identifiers) has
    // been seen on the internet for at least this number of days.
    int32 active_days_lower_bound = 1
        [(google.api.field_behavior) = OUTPUT_ONLY];

    // Output only. Likelihood (from 0.0 to 1.0) this user includes synthetic
    // components in their identity, such as a randomly generated email address,
    // temporary phone number, or fake shipping address.
    float synthetic_risk = 2 [(google.api.field_behavior) = OUTPUT_ONLY];
  }

  // Signals describing the payment card used in this transaction.
  message CardSignals {
    // Risk labels describing the card being assessed, such as its funding
    // mechanism.
    enum CardLabel {
      // No label specified.
      CARD_LABEL_UNSPECIFIED = 0;

      // This card has been detected as prepaid.
      PREPAID = 1;

      // This card has been detected as virtual, such as a card number generated
      // for a single transaction or merchant.
      VIRTUAL = 2;

      // This card has been detected as being used in an unexpected geographic
      // location.
      UNEXPECTED_LOCATION = 3;
    }

    // Output only. The labels for the payment card in this transaction.
    repeated CardLabel card_labels = 1
        [(google.api.field_behavior) = OUTPUT_ONLY];
  }

  // Output only. Signals describing the end user in this transaction.
  UserSignals user_signals = 1 [(google.api.field_behavior) = OUTPUT_ONLY];

  // Output only. Signals describing the payment card or cards used in this
  // transaction.
  CardSignals card_signals = 2 [(google.api.field_behavior) = OUTPUT_ONLY];
}

// Account defender risk assessment.
message AccountDefenderAssessment {
  // Labels returned by account defender for this request.
  enum AccountDefenderLabel {
    // Default unspecified type.
    ACCOUNT_DEFENDER_LABEL_UNSPECIFIED = 0;

    // The request matches a known good profile for the user.
    PROFILE_MATCH = 1;

    // The request is potentially a suspicious login event and must be further
    // verified either through multi-factor authentication or another system.
    SUSPICIOUS_LOGIN_ACTIVITY = 2;

    // The request matched a profile that previously had suspicious account
    // creation behavior. This can mean that this is a fake account.
    SUSPICIOUS_ACCOUNT_CREATION = 3;

    // The account in the request has a high number of related accounts. It does
    // not necessarily imply that the account is bad but can require further
    // investigation.
    RELATED_ACCOUNTS_NUMBER_HIGH = 4;
  }

  // Output only. Labels for this request.
  repeated AccountDefenderLabel labels = 1
      [(google.api.field_behavior) = OUTPUT_ONLY];
}

// The create key request message.
message CreateKeyRequest {
  // Required. The name of the project in which the key will be created, in the
  // format `projects/{project}`.
  string parent = 1 [
    (google.api.field_behavior) = REQUIRED,
    (google.api.resource_reference) = {
      type: "cloudresourcemanager.googleapis.com/Project"
    }
  ];

  // Required. Information to create a reCAPTCHA Enterprise key.
  Key key = 2 [(google.api.field_behavior) = REQUIRED];
}

// The list keys request message.
message ListKeysRequest {
  // Required. The name of the project that contains the keys that will be
  // listed, in the format `projects/{project}`.
  string parent = 1 [
    (google.api.field_behavior) = REQUIRED,
    (google.api.resource_reference) = {
      type: "cloudresourcemanager.googleapis.com/Project"
    }
  ];

  // Optional. The maximum number of keys to return. Default is 10. Max limit is
  // 1000.
  int32 page_size = 2 [(google.api.field_behavior) = OPTIONAL];

  // Optional. The next_page_token value returned from a previous.
  // ListKeysRequest, if any.
  string page_token = 3 [(google.api.field_behavior) = OPTIONAL];
}

// Response to request to list keys in a project.
message ListKeysResponse {
  // Key details.
  repeated Key keys = 1;

  // Token to retrieve the next page of results. It is set to empty if no keys
  // remain in results.
  string next_page_token = 2;
}

// The retrieve legacy secret key request message.
message RetrieveLegacySecretKeyRequest {
  // Required. The public key name linked to the requested secret key in the
  // format `projects/{project}/keys/{key}`.
  string key = 1 [
    (google.api.field_behavior) = REQUIRED,
    (google.api.resource_reference) = {
      type: "recaptchaenterprise.googleapis.com/Key"
    }
  ];
}

// The get key request message.
message GetKeyRequest {
  // Required. The name of the requested key, in the format
  // `projects/{project}/keys/{key}`.
  string name = 1 [
    (google.api.field_behavior) = REQUIRED,
    (google.api.resource_reference) = {
      type: "recaptchaenterprise.googleapis.com/Key"
    }
  ];
}

// The update key request message.
message UpdateKeyRequest {
  // Required. The key to update.
  Key key = 1 [(google.api.field_behavior) = REQUIRED];

  // Optional. The mask to control which fields of the key get updated. If the
  // mask is not present, all fields will be updated.
  google.protobuf.FieldMask update_mask = 2
      [(google.api.field_behavior) = OPTIONAL];
}

// The delete key request message.
message DeleteKeyRequest {
  // Required. The name of the key to be deleted, in the format
  // `projects/{project}/keys/{key}`.
  string name = 1 [
    (google.api.field_behavior) = REQUIRED,
    (google.api.resource_reference) = {
      type: "recaptchaenterprise.googleapis.com/Key"
    }
  ];
}

// The create firewall policy request message.
message CreateFirewallPolicyRequest {
  // Required. The name of the project this policy will apply to, in the format
  // `projects/{project}`.
  string parent = 1 [
    (google.api.field_behavior) = REQUIRED,
    (google.api.resource_reference) = {
      type: "cloudresourcemanager.googleapis.com/Project"
    }
  ];

  // Required. Information to create the policy.
  FirewallPolicy firewall_policy = 2 [(google.api.field_behavior) = REQUIRED];
}

// The list firewall policies request message.
message ListFirewallPoliciesRequest {
  // Required. The name of the project to list the policies for, in the format
  // `projects/{project}`.
  string parent = 1 [
    (google.api.field_behavior) = REQUIRED,
    (google.api.resource_reference) = {
      type: "cloudresourcemanager.googleapis.com/Project"
    }
  ];

  // Optional. The maximum number of policies to return. Default is 10. Max
  // limit is 1000.
  int32 page_size = 2 [(google.api.field_behavior) = OPTIONAL];

  // Optional. The next_page_token value returned from a previous.
  // ListFirewallPoliciesRequest, if any.
  string page_token = 3 [(google.api.field_behavior) = OPTIONAL];
}

// Response to request to list firewall policies belonging to a key.
message ListFirewallPoliciesResponse {
  // Policy details.
  repeated FirewallPolicy firewall_policies = 1;

  // Token to retrieve the next page of results. It is set to empty if no
  // policies remain in results.
  string next_page_token = 2;
}

// The get firewall policy request message.
message GetFirewallPolicyRequest {
  // Required. The name of the requested policy, in the format
  // `projects/{project}/firewallpolicies/{firewallpolicy}`.
  string name = 1 [
    (google.api.field_behavior) = REQUIRED,
    (google.api.resource_reference) = {
      type: "recaptchaenterprise.googleapis.com/FirewallPolicy"
    }
  ];
}

// The update firewall policy request message.
message UpdateFirewallPolicyRequest {
  // Required. The policy to update.
  FirewallPolicy firewall_policy = 1 [(google.api.field_behavior) = REQUIRED];

  // Optional. The mask to control which fields of the policy get updated. If
  // the mask is not present, all fields will be updated.
  google.protobuf.FieldMask update_mask = 2
      [(google.api.field_behavior) = OPTIONAL];
}

// The delete firewall policy request message.
message DeleteFirewallPolicyRequest {
  // Required. The name of the policy to be deleted, in the format
  // `projects/{project}/firewallpolicies/{firewallpolicy}`.
  string name = 1 [
    (google.api.field_behavior) = REQUIRED,
    (google.api.resource_reference) = {
      type: "recaptchaenterprise.googleapis.com/FirewallPolicy"
    }
  ];
}

// The migrate key request message.
message MigrateKeyRequest {
  // Required. The name of the key to be migrated, in the format
  // `projects/{project}/keys/{key}`.
  string name = 1 [
    (google.api.field_behavior) = REQUIRED,
    (google.api.resource_reference) = {
      type: "recaptchaenterprise.googleapis.com/Key"
    }
  ];

  // Optional. If true, skips the billing check.
  // A reCAPTCHA Enterprise key or migrated key behaves differently than a
  // reCAPTCHA (non-Enterprise version) key when you reach a quota limit (see
  // https://cloud.google.com/recaptcha-enterprise/quotas#quota_limit). To avoid
  // any disruption of your usage, we check that a billing account is present.
  // If your usage of reCAPTCHA is under the free quota, you can safely skip the
  // billing check and proceed with the migration. See
  // https://cloud.google.com/recaptcha-enterprise/docs/billing-information.
  bool skip_billing_check = 2 [(google.api.field_behavior) = OPTIONAL];
}

// The get metrics request message.
message GetMetricsRequest {
  // Required. The name of the requested metrics, in the format
  // `projects/{project}/keys/{key}/metrics`.
  string name = 1 [
    (google.api.field_behavior) = REQUIRED,
    (google.api.resource_reference) = {
      type: "recaptchaenterprise.googleapis.com/Metrics"
    }
  ];
}

// Metrics for a single Key.
message Metrics {
  option (google.api.resource) = {
    type: "recaptchaenterprise.googleapis.com/Metrics"
    pattern: "projects/{project}/keys/{key}/metrics"
  };

  // Output only. Identifier. The name of the metrics, in the format
  // `projects/{project}/keys/{key}/metrics`.
  string name = 4 [
    (google.api.field_behavior) = IDENTIFIER,
    (google.api.field_behavior) = OUTPUT_ONLY
  ];

  // Inclusive start time aligned to a day (UTC).
  google.protobuf.Timestamp start_time = 1;

  // Metrics will be continuous and in order by dates, and in the granularity
  // of day. All Key types should have score-based data.
  repeated ScoreMetrics score_metrics = 2;

  // Metrics will be continuous and in order by dates, and in the granularity
  // of day. Only challenge-based keys (CHECKBOX, INVISIBLE), will have
  // challenge-based data.
  repeated ChallengeMetrics challenge_metrics = 3;
}

// Secret key is used only in legacy reCAPTCHA. It must be used in a 3rd party
// integration with legacy reCAPTCHA.
message RetrieveLegacySecretKeyResponse {
  // The secret key (also known as shared secret) authorizes communication
  // between your application backend and the reCAPTCHA Enterprise server to
  // create an assessment.
  // The secret key needs to be kept safe for security purposes.
  string legacy_secret_key = 1;
}

// A key used to identify and configure applications (web and/or mobile) that
// use reCAPTCHA Enterprise.
message Key {
  option (google.api.resource) = {
    type: "recaptchaenterprise.googleapis.com/Key"
    pattern: "projects/{project}/keys/{key}"
  };

  // Identifier. The resource name for the Key in the format
  // `projects/{project}/keys/{key}`.
  string name = 1 [(google.api.field_behavior) = IDENTIFIER];

  // Required. Human-readable display name of this key. Modifiable by user.
  string display_name = 2 [(google.api.field_behavior) = REQUIRED];

  // Platform-specific settings for this key. The key can only be used on a
  // platform for which the settings are enabled.
  oneof platform_settings {
    // Settings for keys that can be used by websites.
    WebKeySettings web_settings = 3;

    // Settings for keys that can be used by Android apps.
    AndroidKeySettings android_settings = 4;

    // Settings for keys that can be used by iOS apps.
    IOSKeySettings ios_settings = 5;
  }

  // Optional. See [Creating and managing labels]
  // (https://cloud.google.com/recaptcha-enterprise/docs/labels).
  map<string, string> labels = 6 [(google.api.field_behavior) = OPTIONAL];

  // Output only. The timestamp corresponding to the creation of this key.
  google.protobuf.Timestamp create_time = 7
      [(google.api.field_behavior) = OUTPUT_ONLY];

  // Optional. Options for user acceptance testing.
  TestingOptions testing_options = 9 [(google.api.field_behavior) = OPTIONAL];

  // Optional. Settings for WAF
  WafSettings waf_settings = 10 [(google.api.field_behavior) = OPTIONAL];
}

// Options for user acceptance testing.
message TestingOptions {
  // Enum that represents the challenge option for challenge-based (CHECKBOX,
  // INVISIBLE) testing keys.
  enum TestingChallenge {
    // Perform the normal risk analysis and return either nocaptcha or a
    // challenge depending on risk and trust factors.
    TESTING_CHALLENGE_UNSPECIFIED = 0;

    // Challenge requests for this key always return a nocaptcha, which
    // does not require a solution.
    NOCAPTCHA = 1;

    // Challenge requests for this key always return an unsolvable
    // challenge.
    UNSOLVABLE_CHALLENGE = 2;
  }

  // Optional. All assessments for this Key will return this score. Must be
  // between 0 (likely not legitimate) and 1 (likely legitimate) inclusive.
  float testing_score = 1 [(google.api.field_behavior) = OPTIONAL];

  // Optional. For challenge-based keys only (CHECKBOX, INVISIBLE), all
  // challenge requests for this site will return nocaptcha if NOCAPTCHA, or an
  // unsolvable challenge if CHALLENGE.
  TestingChallenge testing_challenge = 2
      [(google.api.field_behavior) = OPTIONAL];
}

// Settings specific to keys that can be used by websites.
message WebKeySettings {
  // Enum that represents the integration types for web keys.
  enum IntegrationType {
    // Default type that indicates this enum hasn't been specified. This is not
    // a valid IntegrationType, one of the other types must be specified
    // instead.
    INTEGRATION_TYPE_UNSPECIFIED = 0;

    // Only used to produce scores. It doesn't display the "I'm not a robot"
    // checkbox and never shows captcha challenges.
    SCORE = 1;

    // Displays the "I'm not a robot" checkbox and may show captcha challenges
    // after it is checked.
    CHECKBOX = 2;

    // Doesn't display the "I'm not a robot" checkbox, but may show captcha
    // challenges after risk analysis.
    INVISIBLE = 3;
  }

  // Enum that represents the possible challenge frequency and difficulty
  // configurations for a web key.
  enum ChallengeSecurityPreference {
    // Default type that indicates this enum hasn't been specified.
    CHALLENGE_SECURITY_PREFERENCE_UNSPECIFIED = 0;

    // Key tends to show fewer and easier challenges.
    USABILITY = 1;

    // Key tends to show balanced (in amount and difficulty) challenges.
    BALANCE = 2;

    // Key tends to show more and harder challenges.
    SECURITY = 3;
  }

  // Optional. If set to true, it means allowed_domains will not be enforced.
  bool allow_all_domains = 3 [(google.api.field_behavior) = OPTIONAL];

  // Optional. Domains or subdomains of websites allowed to use the key. All
  // subdomains of an allowed domain are automatically allowed. A valid domain
  // requires a host and must not include any path, port, query or fragment.
  // Examples: 'example.com' or 'subdomain.example.com'
  repeated string allowed_domains = 1 [(google.api.field_behavior) = OPTIONAL];

  // Optional. If set to true, the key can be used on AMP (Accelerated Mobile
  // Pages) websites. This is supported only for the SCORE integration type.
  bool allow_amp_traffic = 2 [(google.api.field_behavior) = OPTIONAL];

  // Required. Describes how this key is integrated with the website.
  IntegrationType integration_type = 4 [(google.api.field_behavior) = REQUIRED];

  // Optional. Settings for the frequency and difficulty at which this key
  // triggers captcha challenges. This should only be specified for
  // IntegrationTypes CHECKBOX and INVISIBLE.
  ChallengeSecurityPreference challenge_security_preference = 5
      [(google.api.field_behavior) = OPTIONAL];
}

// Settings specific to keys that can be used by Android apps.
message AndroidKeySettings {
  // Optional. If set to true, allowed_package_names are not enforced.
  bool allow_all_package_names = 2 [(google.api.field_behavior) = OPTIONAL];

  // Optional. Android package names of apps allowed to use the key.
  // Example: 'com.companyname.appname'
  repeated string allowed_package_names = 1
      [(google.api.field_behavior) = OPTIONAL];

  // Optional. Set to true for keys that are used in an Android application that
  // is available for download in app stores in addition to the Google Play
  // Store.
  bool support_non_google_app_store_distribution = 3
      [(google.api.field_behavior) = OPTIONAL];
}

// Settings specific to keys that can be used by iOS apps.
message IOSKeySettings {
  // Optional. If set to true, allowed_bundle_ids are not enforced.
  bool allow_all_bundle_ids = 2 [(google.api.field_behavior) = OPTIONAL];

  // Optional. iOS bundle ids of apps allowed to use the key.
  // Example: 'com.companyname.productname.appname'
  repeated string allowed_bundle_ids = 1
      [(google.api.field_behavior) = OPTIONAL];

  // Optional. Apple Developer account details for the app that is protected by
  // the reCAPTCHA Key. reCAPTCHA Enterprise leverages platform-specific checks
  // like Apple App Attest and Apple DeviceCheck to protect your app from abuse.
  // Providing these fields allows reCAPTCHA Enterprise to get a better
  // assessment of the integrity of your app.
  AppleDeveloperId apple_developer_id = 3
      [(google.api.field_behavior) = OPTIONAL];
}

// Contains fields that are required to perform Apple-specific integrity checks.
message AppleDeveloperId {
  // Required. Input only. A private key (downloaded as a text file with a .p8
  // file extension) generated for your Apple Developer account. Ensure that
  // Apple DeviceCheck is enabled for the private key.
  string private_key = 1 [
    (google.api.field_behavior) = REQUIRED,
    (google.api.field_behavior) = INPUT_ONLY
  ];

  // Required. The Apple developer key ID (10-character string).
  string key_id = 2 [(google.api.field_behavior) = REQUIRED];

  // Required. The Apple team ID (10-character string) owning the provisioning
  // profile used to build your application.
  string team_id = 3 [(google.api.field_behavior) = REQUIRED];
}

// Score distribution.
message ScoreDistribution {
  // Map key is score value multiplied by 100. The scores are discrete values
  // between [0, 1]. The maximum number of buckets is on order of a few dozen,
  // but typically much lower (ie. 10).
  map<int32, int64> score_buckets = 1;
}

// Metrics related to scoring.
message ScoreMetrics {
  // Aggregated score metrics for all traffic.
  ScoreDistribution overall_metrics = 1;

  // Action-based metrics. The map key is the action name which specified by the
  // site owners at time of the "execute" client-side call.
  map<string, ScoreDistribution> action_metrics = 2;
}

// Metrics related to challenges.
message ChallengeMetrics {
  // Count of reCAPTCHA checkboxes or badges rendered. This is mostly equivalent
  // to a count of pageloads for pages that include reCAPTCHA.
  int64 pageload_count = 1;

  // Count of nocaptchas (successful verification without a challenge) issued.
  int64 nocaptcha_count = 2;

  // Count of submitted challenge solutions that were incorrect or otherwise
  // deemed suspicious such that a subsequent challenge was triggered.
  int64 failed_count = 3;

  // Count of nocaptchas (successful verification without a challenge) plus
  // submitted challenge solutions that were correct and resulted in
  // verification.
  int64 passed_count = 4;
}

// Policy config assessment.
message FirewallPolicyAssessment {
  // Output only. If the processing of a policy config fails, an error will be
  // populated and the firewall_policy will be left empty.
  google.rpc.Status error = 5 [(google.api.field_behavior) = OUTPUT_ONLY];

  // Output only. The policy that matched the request. If more than one policy
  // may match, this is the first match. If no policy matches the incoming
  // request, the policy field will be left empty.
  FirewallPolicy firewall_policy = 8
      [(google.api.field_behavior) = OUTPUT_ONLY];
}

// An individual action. Each action represents what to do if a policy
// matches.
message FirewallAction {
  // An allow action continues processing a request unimpeded.
  message AllowAction {}

  // A block action serves an HTTP error code a prevents the request from
  // hitting the backend.
  message BlockAction {}

  // A redirect action returns a 307 (temporary redirect) response, pointing
  // the user to a ReCaptcha interstitial page to attach a token.
  message RedirectAction {}

  // A substitute action transparently serves a different page than the one
  // requested.
  message SubstituteAction {
    // Optional. The address to redirect to. The target is a relative path in
    // the current host. Example: "/blog/404.html".
    string path = 1 [(google.api.field_behavior) = OPTIONAL];
  }

  // A set header action sets a header and forwards the request to the
  // backend. This can be used to trigger custom protection implemented on the
  // backend.
  message SetHeaderAction {
    // Optional. The header key to set in the request to the backend server.
    string key = 1 [(google.api.field_behavior) = OPTIONAL];

    // Optional. The header value to set in the request to the backend server.
    string value = 2 [(google.api.field_behavior) = OPTIONAL];
  }

  oneof firewall_action_oneof {
    // The user request did not match any policy and should be allowed
    // access to the requested resource.
    AllowAction allow = 1;

    // This action will deny access to a given page. The user will get an HTTP
    // error code.
    BlockAction block = 2;

    // This action will redirect the request to a ReCaptcha interstitial to
    // attach a token.
    RedirectAction redirect = 5;

    // This action will transparently serve a different page to an offending
    // user.
    SubstituteAction substitute = 3;

    // This action will set a custom header but allow the request to continue
    // to the customer backend.
    SetHeaderAction set_header = 4;
  }
}

// A FirewallPolicy represents a single matching pattern and resulting actions
// to take.
message FirewallPolicy {
  option (google.api.resource) = {
    type: "recaptchaenterprise.googleapis.com/FirewallPolicy"
    pattern: "projects/{project}/firewallpolicies/{firewallpolicy}"
  };

  // Identifier. The resource name for the FirewallPolicy in the format
  // `projects/{project}/firewallpolicies/{firewallpolicy}`.
  string name = 1 [(google.api.field_behavior) = IDENTIFIER];

  // Optional. A description of what this policy aims to achieve, for
  // convenience purposes. The description can at most include 256 UTF-8
  // characters.
  string description = 2 [(google.api.field_behavior) = OPTIONAL];

  // Optional. The path for which this policy applies, specified as a glob
  // pattern. For more information on glob, see the [manual
  // page](https://man7.org/linux/man-pages/man7/glob.7.html).
  // A path has a max length of 200 characters.
  string path = 4 [(google.api.field_behavior) = OPTIONAL];

  // Optional. A CEL (Common Expression Language) conditional expression that
  // specifies if this policy applies to an incoming user request. If this
  // condition evaluates to true and the requested path matched the path
  // pattern, the associated actions should be executed by the caller. The
  // condition string is checked for CEL syntax correctness on creation. For
  // more information, see the [CEL spec](https://github.com/google/cel-spec)
  // and its [language
  // definition](https://github.com/google/cel-spec/blob/master/doc/langdef.md).
  // A condition has a max length of 500 characters.
  string condition = 5 [(google.api.field_behavior) = OPTIONAL];

  // Optional. The actions that the caller should take regarding user access.
  // There should be at most one terminal action. A terminal action is any
  // action that forces a response, such as `AllowAction`,
  // `BlockAction` or `SubstituteAction`.
  // Zero or more non-terminal actions such as `SetHeader` might be
  // specified. A single policy can contain up to 16 actions.
  repeated FirewallAction actions = 6 [(google.api.field_behavior) = OPTIONAL];
}

// The request message to list memberships in a related account group.
message ListRelatedAccountGroupMembershipsRequest {
  // Required. The resource name for the related account group in the format
  // `projects/{project}/relatedaccountgroups/{relatedaccountgroup}`.
  string parent = 1 [
    (google.api.field_behavior) = REQUIRED,
    (google.api.resource_reference) = {
      child_type: "recaptchaenterprise.googleapis.com/RelatedAccountGroupMembership"
    }
  ];

  // Optional. The maximum number of accounts to return. The service might
  // return fewer than this value. If unspecified, at most 50 accounts are
  // returned. The maximum value is 1000; values above 1000 are coerced to 1000.
  int32 page_size = 2 [(google.api.field_behavior) = OPTIONAL];

  // Optional. A page token, received from a previous
  // `ListRelatedAccountGroupMemberships` call.
  //
  // When paginating, all other parameters provided to
  // `ListRelatedAccountGroupMemberships` must match the call that provided the
  // page token.
  string page_token = 3 [(google.api.field_behavior) = OPTIONAL];
}

// The response to a `ListRelatedAccountGroupMemberships` call.
message ListRelatedAccountGroupMembershipsResponse {
  // The memberships listed by the query.
  repeated RelatedAccountGroupMembership related_account_group_memberships = 1;

  // A token, which can be sent as `page_token` to retrieve the next page.
  // If this field is omitted, there are no subsequent pages.
  string next_page_token = 2;
}

// The request message to list related account groups.
message ListRelatedAccountGroupsRequest {
  // Required. The name of the project to list related account groups from, in
  // the format `projects/{project}`.
  string parent = 1 [
    (google.api.field_behavior) = REQUIRED,
    (google.api.resource_reference) = {
      child_type: "recaptchaenterprise.googleapis.com/RelatedAccountGroup"
    }
  ];

  // Optional. The maximum number of groups to return. The service might return
  // fewer than this value. If unspecified, at most 50 groups are returned. The
  // maximum value is 1000; values above 1000 are coerced to 1000.
  int32 page_size = 2 [(google.api.field_behavior) = OPTIONAL];

  // Optional. A page token, received from a previous `ListRelatedAccountGroups`
  // call. Provide this to retrieve the subsequent page.
  //
  // When paginating, all other parameters provided to
  // `ListRelatedAccountGroups` must match the call that provided the page
  // token.
  string page_token = 3 [(google.api.field_behavior) = OPTIONAL];
}

// The response to a `ListRelatedAccountGroups` call.
message ListRelatedAccountGroupsResponse {
  // The groups of related accounts listed by the query.
  repeated RelatedAccountGroup related_account_groups = 1;

  // A token, which can be sent as `page_token` to retrieve the next page.
  // If this field is omitted, there are no subsequent pages.
  string next_page_token = 2;
}

// The request message to search related account group memberships.
message SearchRelatedAccountGroupMembershipsRequest {
  // Required. The name of the project to search related account group
  // memberships from. Specify the project name in the following format:
  // `projects/{project}`.
  string project = 1 [
    (google.api.field_behavior) = REQUIRED,
    (google.api.resource_reference) = {
      child_type: "recaptchaenterprise.googleapis.com/RelatedAccountGroupMembership"
    }
  ];

  // Optional. The unique stable account identifier used to search connections.
  // The identifier should correspond to an `account_id` provided in a previous
  // `CreateAssessment` or `AnnotateAssessment` call. Either hashed_account_id
  // or account_id must be set, but not both.
  string account_id = 5 [(google.api.field_behavior) = OPTIONAL];

  // Optional. Deprecated: use `account_id` instead.
  // The unique stable hashed account identifier used to search connections. The
  // identifier should correspond to a `hashed_account_id` provided in a
  // previous `CreateAssessment` or `AnnotateAssessment` call. Either
  // hashed_account_id or account_id must be set, but not both.
  bytes hashed_account_id = 2
      [deprecated = true, (google.api.field_behavior) = OPTIONAL];

  // Optional. The maximum number of groups to return. The service might return
  // fewer than this value. If unspecified, at most 50 groups are returned. The
  // maximum value is 1000; values above 1000 are coerced to 1000.
  int32 page_size = 3 [(google.api.field_behavior) = OPTIONAL];

  // Optional. A page token, received from a previous
  // `SearchRelatedAccountGroupMemberships` call. Provide this to retrieve the
  // subsequent page.
  //
  // When paginating, all other parameters provided to
  // `SearchRelatedAccountGroupMemberships` must match the call that provided
  // the page token.
  string page_token = 4 [(google.api.field_behavior) = OPTIONAL];
}

// The response to a `SearchRelatedAccountGroupMemberships` call.
message SearchRelatedAccountGroupMembershipsResponse {
  // The queried memberships.
  repeated RelatedAccountGroupMembership related_account_group_memberships = 1;

  // A token, which can be sent as `page_token` to retrieve the next page.
  // If this field is omitted, there are no subsequent pages.
  string next_page_token = 2;
}

// A membership in a group of related accounts.
message RelatedAccountGroupMembership {
  option (google.api.resource) = {
    type: "recaptchaenterprise.googleapis.com/RelatedAccountGroupMembership"
    pattern: "projects/{project}/relatedaccountgroups/{relatedaccountgroup}/memberships/{membership}"
  };

  // Required. Identifier. The resource name for this membership in the format
  // `projects/{project}/relatedaccountgroups/{relatedaccountgroup}/memberships/{membership}`.
  string name = 1 [
    (google.api.field_behavior) = IDENTIFIER,
    (google.api.field_behavior) = REQUIRED,
    (google.api.resource_reference) = {
      type: "recaptchaenterprise.googleapis.com/RelatedAccountGroupMembership"
    }
  ];

  // The unique stable account identifier of the member. The identifier
  // corresponds to an `account_id` provided in a previous `CreateAssessment` or
  // `AnnotateAssessment` call.
  string account_id = 4;

  // Deprecated: use `account_id` instead.
  // The unique stable hashed account identifier of the member. The identifier
  // corresponds to a `hashed_account_id` provided in a previous
  // `CreateAssessment` or `AnnotateAssessment` call.
  bytes hashed_account_id = 2 [deprecated = true];
}

// A group of related accounts.
message RelatedAccountGroup {
  option (google.api.resource) = {
    type: "recaptchaenterprise.googleapis.com/RelatedAccountGroup"
    pattern: "projects/{project}/relatedaccountgroups/{relatedaccountgroup}"
  };

  // Required. Identifier. The resource name for the related account group in
  // the format
  // `projects/{project}/relatedaccountgroups/{related_account_group}`.
  string name = 1 [
    (google.api.field_behavior) = IDENTIFIER,
    (google.api.field_behavior) = REQUIRED,
    (google.api.resource_reference) = {
      type: "recaptchaenterprise.googleapis.com/RelatedAccountGroup"
    }
  ];
}

// Settings specific to keys that can be used for WAF (Web Application
// Firewall).
message WafSettings {
  // Supported WAF features. For more information, see
  // https://cloud.google.com/recaptcha-enterprise/docs/usecase#comparison_of_features.
  enum WafFeature {
    // Undefined feature.
    WAF_FEATURE_UNSPECIFIED = 0;

    // Redirects suspicious traffic to reCAPTCHA.
    CHALLENGE_PAGE = 1;

    // Use reCAPTCHA session-tokens to protect the whole user session on the
    // site's domain.
    SESSION_TOKEN = 2;

    // Use reCAPTCHA action-tokens to protect user actions.
    ACTION_TOKEN = 3;

    // Use reCAPTCHA WAF express protection to protect any content other than
    // web pages, like APIs and IoT devices.
    EXPRESS = 5;
  }

  // Web Application Firewalls supported by reCAPTCHA Enterprise.
  enum WafService {
    // Undefined WAF
    WAF_SERVICE_UNSPECIFIED = 0;

    // Cloud Armor
    CA = 1;

    // Fastly
    FASTLY = 3;
  }

  // Required. The WAF service that uses this key.
  WafService waf_service = 1 [(google.api.field_behavior) = REQUIRED];

  // Required. The WAF feature for which this key is enabled.
  WafFeature waf_feature = 2 [(google.api.field_behavior) = REQUIRED];
}
