syntax = "proto3";

import "google/api/annotations.proto";
import "google/protobuf/struct.proto";
import "wix/spi/definitions.proto";
import "wix/common/spi.proto";
import "google/protobuf/wrappers.proto";
import "wix/api/validations.proto";
import "wix/api/annotations.proto";
import "google/protobuf/timestamp.proto";

package com.wixpress.appservice.api.upstream.wix.iam.authentication.v1;

service FactorSpi {
  option (.wix.spi.service) = {
    spi_identifier: "com.wixpress.appservice.api.ComponentType.IDENTITY_FACTOR"
    config_message: "com.wixpress.appservice.api.upstream.wix.iam.authentication.v1.FactorConfig"
    host_service: "wix.iam.authentication.v1.AuthenticationService"
    app_id: "eb377299-86b4-4a86-a1b5-774a2d1d374b"
    fqdn: "wix.interfaces.iam.v1.factor"
  };

  // enroll a factor
  rpc Enroll(EnrollRequest) returns (EnrollResponse) {
    option (google.api.http) = {
      post: "/v1/enroll"
    };
  }

  // verify a factor
  rpc Verify(VerifyRequest) returns (VerifyResponse) {
    option (google.api.http) = {
      post: "/v1/verify"
    };
  }

  // Gets factor data for a given identity.
  rpc Get(GetRequest) returns (GetResponse) {
    option (google.api.http) = {
      post: "/v1/get"
    };
  }

  // Unenrolls a factor for a given identity.
  rpc Unenroll(UnenrollRequest) returns (UnenrollResponse) {
    option (google.api.http) = {
      post: "/v1/unenroll"
    };
  }
}

enum FactorType {
  UNKNOWN_FACTOR_TYPE = 0 [(.wix.api.enum_maturity) = NOT_IMPLEMENTED]; // Unknown factor type.
  PASSWORD = 1; // Requires a password.
  SMS = 2; // Requires a code sent via SMS.
  CALL = 3; // Requires a code sent by phone call.
  EMAIL = 4; // Requires a code sent by email.
  TOTP = 6; // Requires authentication via an authenticator app.
  PUSH = 7; // Requires authentication via a push notification.
  WEBAUTHN = 8; // Requires authentication via WebAuthn/passkey.
  RECOVERY_CODE = 9; // Requires a recovery code.
}

message PasswordData {
    option (.wix.api.decomposite_of) = "wix.iam.authentication.factor.v1.PasswordData";
  string password = 1 [(.wix.api.maxLength) = 256];
  // To maintain backwards compatibility, password factors are associated with an identity_id.
  string identity_id = 2 [(.wix.api.format) = GUID, (.wix.api.field_exposure) = PRIVATE, deprecated = true, (.wix.api.field_deprecated) = {
    target_removal_date: "2024-12-31"
  }];
}

message SmsEnrollData {
    option (.wix.api.decomposite_of) = "wix.iam.authentication.factor.v1.SmsEnrollData";
  string phone_number = 1 [(.wix.api.pii) = true, (.wix.api.format) = PHONE];
}

//message CallEnrollData {
//  string phone_number = 1 [(.wix.api.pii) = true, (wix.api.format) = PHONE]; // check that the format contains extension
//}



message EmailEnrollData {
    option (.wix.api.decomposite_of) = "wix.iam.authentication.factor.v1.EmailEnrollData";
  string email = 1 [(.wix.api.pii) = true, (.wix.api.format) = EMAIL];
}

//message PushEnrollData {
//  google.protobuf.StringValue device_id = 1 [(wix.api.format) = GUID];
//}

message WebAuthnEnrollData {
    option (.wix.api.decomposite_of) = "wix.iam.authentication.factor.v1.WebAuthnEnrollData";
  // Recommended user name to display in the WebAuthn UI. 
  // The factor implementer may return a different value in the response if needed.
  string user_name = 1 [(.wix.api.minLength) = 1, (.wix.api.maxLength) = 100];
  // Recommended user display name to show in the WebAuthn UI. 
  // The factor implementer may return a different value in the response if needed.
  string user_display_name = 2 [(.wix.api.minLength) = 1, (.wix.api.maxLength) = 100];
  
  // If this field is present, this is a request to complete the WebAuthn registration
  // with the credential data from the client.
  //
  // The credential contains a JSON string representation of a WebAuthn PublicKeyCredential
  // object returned by the browser during registration, serialized as per the WebAuthn specification.
  // The SPI implementation should use this to create and return a WebAuthnCredentialInfo
  // in the WebAuthnEnrollmentCompleteData response.
  //
  // Any standards-compliant WebAuthn server library should be able to process this serialized format.
  // For details on the serialization format, refer to the W3C WebAuthn specification:
  // https://www.w3.org/TR/webauthn-3/#dom-publickeycredential-tojson
  google.protobuf.StringValue credential = 3 [(.wix.api.maxLength) = 3000];
}

// flynt-disable deleted-field-enum-reserved
message EnrollRequest {
    option (.wix.api.decomposite_of) = "wix.iam.authentication.factor.v1.EnrollRequest";
  google.protobuf.StringValue identity_id = 3 [(.wix.api.format) = GUID];
  FactorType factor_type = 1;
  oneof factor_data {
    option (.wix.api.aligned_with_enum) = {
      field: "factor_type";
      suffix: "data";
    };
    PasswordData password_data = 2;
    SmsEnrollData sms_data = 4;
    //CallEnrollData call_data = 5;
    EmailEnrollData email_data = 6;
    //PushEnrollData push_data = 7;
    WebAuthnEnrollData webauthn_data = 8;
  }
}

enum EnrollmentStatus {
  UNKNOWN_ENROLLMENT_STATUS = 0 [(.wix.api.enum_maturity) = NOT_IMPLEMENTED];
  // The Factor is enrolled and ready to be used.
  ENROLLMENT_COMPLETE = 1;
  // The Factor is not enrolled and cannot be used. The response may contain a challenge to enroll the Factor successfully.
  ENROLLMENT_INCOMPLETE = 2;
  // The Factor cannot be enrolled.
  ENROLLMENT_FAILED = 3;
}

message TotpEnrollmentCompleteData {
    option (.wix.api.decomposite_of) = "wix.iam.authentication.factor.v1.TotpEnrollmentCompleteData";
  string secret = 1 [(.wix.api.minLength) = 1, (.wix.api.maxLength) = 100]; // maxLength?
  Algorithm algorithm = 2;
  int32 digits = 3;
  int32 period = 4;

  enum Algorithm {
      SHA1 = 0;
      SHA256 = 1;
      SHA512 = 2;
  }
}

message WebAuthnEnrollmentCompleteData {
    option (.wix.api.decomposite_of) = "wix.iam.authentication.factor.v1.WebAuthnEnrollmentCompleteData";
  // Information about the newly created WebAuthn credential
  WebAuthnCredentialInfo credential_info = 1;
}

message PushEnrollmentCompleteData {
    option (.wix.api.decomposite_of) = "wix.iam.authentication.factor.v1.PushEnrollmentCompleteData";
  // Happens where there is a device where the user is logged in to the app.
  // PushDeviceData push_device_data = 1;
}

//message PushDeviceData {
//  google.protobuf.StringValue device_id = 1 [(wix.api.format) = GUID];
//  google.protobuf.StringValue device_name = 2 [(wix.api.minLength) = 1, (wix.api.maxLength) = 100];
//}

message RecoveryCodeEnrollmentCompleteData {
    option (.wix.api.decomposite_of) = "wix.iam.authentication.factor.v1.RecoveryCodeEnrollmentCompleteData";
  repeated string recovery_codes = 1 [(.wix.api.minSize) = 1, (.wix.api.maxSize) = 20, (.wix.api.minLength) = 1, (.wix.api.maxLength) = 100];
}

// flynt-disable deleted-field-enum-reserved
message EnrollmentComplete {
    option (.wix.api.decomposite_of) = "wix.iam.authentication.factor.v1.EnrollmentComplete";
  // The Factor is enrolled and ready to be used.
  // Optional data to deliver to the client after successful enrollment. This data is specific to the FactorType, eg. TOTP secret and settings.
  oneof factor_data {
    TotpEnrollmentCompleteData totp_data = 2;
    //PushEnrollmentCompleteData push_data = 3;
    WebAuthnEnrollmentCompleteData webauthn_data = 4;
    RecoveryCodeEnrollmentCompleteData recovery_code_data = 5;
  }
}

message EnrollmentChallenge {
  option (.wix.api.decomposite_of) = "wix.iam.authentication.factor.v1.EnrollmentChallenge";
}

//message PushDevicesData {
//  repeated PushDeviceData push_device_data = 2;
//}
//
//message PushEnrollmentInCompleteData {
//  oneof device_data{
//    // Happens when the user does not have the app installed or he is not logged in.
//    // The URL to display to complete the enrollment process on the user's push-enabled device.
//    string enrollment_url = 1 [(wix.api.format) = WEB_URL];
//    // Happens when the user is logged in to one or more devices and the enroll request did not include a deviceId
//    // (or the request included a deviceId and the user is not logged in to that device).
//    PushDevicesData push_devices_data = 2;
//  }
//}

message EnrollmentIncomplete {
    option (.wix.api.decomposite_of) = "wix.iam.authentication.factor.v1.EnrollmentIncomplete";
  oneof factor_data {
    WebAuthnEnrollmentIncompleteData webauthn_data = 3;
  }
}

message WebAuthnEnrollmentIncompleteData {
    option (.wix.api.decomposite_of) = "wix.iam.authentication.factor.v1.WebAuthnEnrollmentIncompleteData";
  // The challenge that will be signed by the authenticator during the WebAuthn registration ceremony.
  // This should be a cryptographically secure random value with at least 16 bytes of entropy.
  // The value is used to prevent replay attacks and MUST be randomly generated by the implementer.
  bytes challenge = 1;

  // The user name to be displayed during the WebAuthn registration ceremony.
  // This will typically be the same as the user_name provided in the EnrollRequest,
  // though implementers may adjust it if they believe it would benefit the user experience.
  // This is usually the user's username, email, or other identifier.
  string user_name = 2 [(.wix.api.minLength) = 1, (.wix.api.maxLength) = 100];

  // The user display name to be shown during the WebAuthn registration ceremony.
  // This will typically be the same as the user_display_name provided in the EnrollRequest,
  // though implementers may adjust it if they believe it would benefit the user experience.
  // This is usually the user's full name or a more user-friendly identifier.
  string user_display_name = 3 [(.wix.api.minLength) = 1, (.wix.api.maxLength) = 100];

  // The timeout in milliseconds for the WebAuthn registration ceremony.
  // After this time, the challenge will be considered expired and the registration will need to be restarted.
  // This is optional and may be overridden by the client if provided.
  // The WebAuthn spec recommends a timeout of at least 1 minute (60000ms).
  google.protobuf.Int32Value timeout_ms = 4;

  
  message AuthenticatorSelectionCriteria {
        option (.wix.api.decomposite_of) = "wix.iam.authentication.factor.v1.WebAuthnEnrollmentIncompleteData.AuthenticatorSelectionCriteria";
    enum AuthenticatorAttachment {
      // Default unspecified value
      UNSPECIFIED = 0;
      // Built-in authenticator such as fingerprint scanner, FaceID, or Windows Hello
      PLATFORM = 1;
      // External authenticator such as a USB security key or NFC device
      CROSS_PLATFORM = 2;
    }
    enum ResidentKeyRequirement {
      // Default unspecified value
      RESIDENT_KEY_UNSPECIFIED = 0;
      // Require the credential to be client-side discoverable (resident key/passkey)
      RESIDENT_KEY_REQUIRED = 1;
      // Prefer authenticators that support client-side discoverable credentials
      RESIDENT_KEY_PREFERRED = 2;
      // Do not create a client-side discoverable credential
      RESIDENT_KEY_DISCOURAGED = 3;
    }
    
    // Specifies the type of authenticator that should be used.
    AuthenticatorAttachment authenticator_attachment = 1;
    // Specifies the requirement for a resident key (aka. passkey).
    ResidentKeyRequirement resident_key = 2;
    // Specifies the requirement for user verification during the registration ceremony.
    UserVerificationRequirement user_verification = 3;
  }
  // Optional authenticator selection criteria
  AuthenticatorSelectionCriteria authenticator_selection = 6;

  enum AttestationConveyancePreference {
    // Default unspecified value
    ATTESTATION_UNSPECIFIED = 0;
    // The authenticator is not asked to return attestation information
    NONE = 1;
    // The authenticator can return attestation data in a privacy-preserving way
    INDIRECT = 2;
    // The authenticator should return a full attestation statement
    DIRECT = 3;
    // The authenticator should return an attestation statement configured for enterprise use
    ENTERPRISE = 4;
  }
  // Optional attestation settings
  AttestationConveyancePreference attestation = 7;

  // List of acceptable public key algorithms, in order of preference
  // The authenticator will use the first algorithm it supports from this list
  // If empty, defaults to: [ES256, EdDSA, ES384, ES512, RS256, RS384, RS512]
  repeated COSEAlgorithmIdentifier pub_key_cred_params = 8 [(.wix.api.maxSize) = 10];

  // Optional list of credentials to exclude from this registration
  // Helps prevent registering the same authenticator multiple times or authenticators
  // that are already registered to other users
  repeated PublicKeyCredentialDescriptor exclude_credentials = 9 [(.wix.api.maxSize) = 10];

  // Optional hints to guide the client UI
  // Examples include "security-key" to emphasize external authenticators
  // or "client-device" to emphasize built-in authenticators
  repeated string hints = 10 [(.wix.api.maxLength) = 50, (.wix.api.maxSize) = 10];

  // Optional extensions for the registration ceremony
  // Provides additional parameters for specialized WebAuthn functionality
  message RegistrationExtensionInputs {
    option (.wix.api.decomposite_of) = "wix.iam.authentication.factor.v1.RegistrationExtensionInputs";
    // FIDO AppID Exclusion Extension (appidExclude)
    // An AppID used to prevent previously registered U2F authenticators from being re-registered
    // This makes already-registered U2F credentials forward-compatible with the WebAuthn API
    string appid_exclude = 1 [(.wix.api.maxLength) = 256];

    // Credential Properties Extension (credProps)
    // Requests that the authenticator report whether the credential is a resident key
    // Helpful for determining if the credential is a passkey and can be used for passwordless authentication
    bool cred_props = 2;

    enum LargeBlobSupport {
      // Default unspecified value
      LARGE_BLOB_SUPPORT_UNSPECIFIED = 0;
      // Require the authenticator to support storing large blobs
      LARGE_BLOB_SUPPORT_REQUIRED = 1;
      // Prefer authenticators that support storing large blobs
      LARGE_BLOB_SUPPORT_PREFERRED = 2;
    }
    // Large Blob Storage Extension (largeBlob)
    // Controls support for the authenticator's large blob storage capability
    // Allows storing data like encrypted account information that can sync across devices
    LargeBlobSupport large_blob_support = 3;

    // User Verification Method Extension (uvm)
    // Requests the authenticator to report which verification methods were used
    // Examples include fingerprint, PIN, or facial recognition
    bool uvm = 4;
  }
  // Optional extensions for the registration ceremony
  RegistrationExtensionInputs extensions = 11;
}

// flynt-disable deleted-field-enum-reserved
message EnrollResponse {
    option (.wix.api.decomposite_of) = "wix.iam.authentication.factor.v1.EnrollResponse";
  EnrollmentStatus enrollment_status = 1;
  oneof enrollment_result {
    option (.wix.api.aligned_with_enum) = {
      field: "enrollment_status";
      suffix: "data";
    };
    EnrollmentComplete enrollment_complete_data = 2;
    EnrollmentIncomplete enrollment_incomplete_data = 3;
    EnrollmentFailed enrollment_failed_data = 4;
  }
}

message SmsVerificationData {
    option (.wix.api.decomposite_of) = "wix.iam.authentication.factor.v1.SmsVerificationData";
  string phone_number = 1 [(.wix.api.pii) = true, (.wix.api.format) = PHONE];
  google.protobuf.StringValue template_id = 3 [(.wix.api.minLength) = 1, (.wix.api.maxLength) = 100];
  // The code to be verified.
  // If omitted, a new code should be sent to the phone.
  google.protobuf.StringValue code = 2 [(.wix.api.minLength) = 1, (.wix.api.maxLength) = 100];
}

message CallVerificationData {
    option (.wix.api.decomposite_of) = "wix.iam.authentication.factor.v1.CallVerificationData";
  string phone_number = 1 [(.wix.api.pii) = true, (.wix.api.format) = PHONE];
  google.protobuf.StringValue template_id = 3 [(.wix.api.minLength) = 1, (.wix.api.maxLength) = 100];
  // The code to be verified.
  // If omitted, a new code should be sent to the phone.
  google.protobuf.StringValue code = 2 [(.wix.api.minLength) = 1, (.wix.api.maxLength) = 100];
}

message EmailVerificationData {
    option (.wix.api.decomposite_of) = "wix.iam.authentication.factor.v1.EmailVerificationData";
  // The email address to send the verification code to.
  string email = 1 [(.wix.api.pii) = true, (.wix.api.format) = EMAIL];
  // The admin-configured template ID to use for the email.
  // It is the admin's responsibility to ensure the template ID is valid, and implementers should make the set of
  // valid IDs known to admins in order to reasonably expect them to provide a valid ID.
  // If the template ID is nonetheless invalid, the expected behavior is undefined and implementers may respond at their
  // discretion (eg. fall back to a default template, return an error, etc).
  string template_id = 3 [(.wix.api.minLength) = 1, (.wix.api.maxLength) = 100];
  // The code to be verified.
  // If omitted, a new code should be emailed.
  google.protobuf.StringValue code = 2 [(.wix.api.minLength) = 1, (.wix.api.maxLength) = 100];
}

message TotpVerificationData {
    option (.wix.api.decomposite_of) = "wix.iam.authentication.factor.v1.TotpVerificationData";
  // The code to be verified.
  google.protobuf.StringValue code = 2 [(.wix.api.minLength) = 1, (.wix.api.maxLength) = 100];
}

message PushVerificationData {
    option (.wix.api.decomposite_of) = "wix.iam.authentication.factor.v1.PushVerificationData";
  // Will be set to the transaction_id from the push_data field of the previous verify response.
  // If omitted, a new push notification should be sent.
  google.protobuf.StringValue transaction_id = 1 [(.wix.api.maxLength) = 36];
  google.protobuf.StringValue template_id = 2 [(.wix.api.minLength) = 1, (.wix.api.maxLength) = 100];
}

message WebAuthnVerificationData {
    option (.wix.api.decomposite_of) = "wix.iam.authentication.factor.v1.WebAuthnVerificationData";
  // The challenge_id from the WebAuthnChallengeData that was returned in the previous
  // verification response. This will always be present when completing the WebAuthn authentication
  // ceremony with the credential data from the client.
  google.protobuf.StringValue challenge_id = 1 [(.wix.api.format) = GUID];

  // If this field is present, this is a request to complete the WebAuthn authentication
  // with the credential data from the client.
  //
  // The credential contains a JSON string representation of a WebAuthn PublicKeyCredential
  // object returned by the browser during authentication, serialized as per the WebAuthn specification.
  // The SPI implementation should use this to verify the authentication assertion.
  //
  // Any standards-compliant WebAuthn server library should be able to process this serialized format.
  // For details on the serialization format, refer to the W3C WebAuthn specification:
  // https://www.w3.org/TR/webauthn-3/#dom-publickeycredential-tojson
  google.protobuf.StringValue credential = 2 [(.wix.api.maxLength) = 3000];
}

message RecoveryCodeVerificationData {
    option (.wix.api.decomposite_of) = "wix.iam.authentication.factor.v1.RecoveryCodeVerificationData";
  string recovery_code = 1 [(.wix.api.minLength) = 1, (.wix.api.maxLength) = 100];
}

// flynt-disable deleted-field-enum-reserved
message VerifyRequest {
    option (.wix.api.decomposite_of) = "wix.iam.authentication.factor.v1.VerifyRequest";
  // The identity ID to verify. 
  // This is optional for factor type WebAuthn, as passkeys support an authentication ceremony where a 
  // challenge is requested from the implementor before the user identified themselves.
  // For other factor types, the identity ID is always defined.
  google.protobuf.StringValue identity_id = 1 [(.wix.api.format) = GUID];
  FactorType factor_type = 2;
  oneof factor_data {
    option (.wix.api.aligned_with_enum) = {
      field: "factor_type";
      suffix: "data";
    };
    PasswordData password_data = 3;
    SmsVerificationData sms_data = 6;
    CallVerificationData call_data = 7;
    EmailVerificationData email_data = 8;
    TotpVerificationData totp_data = 9;
    PushVerificationData push_data = 10;
    WebAuthnVerificationData webauthn_data = 11;
    RecoveryCodeVerificationData recovery_code_data = 12;
  }
  // flynt-disable missing-string-validations
  string old_identity_id = 5 [deprecated = true, (.wix.api.field_deprecated) = {
    replaced_by: "identity_id",
    target_removal_date: "2025-05-01"
  }];
}

enum VerificationStatus {
  UNKNOWN_VERIFICATION_STATUS = 0 [(.wix.api.enum_maturity) = NOT_IMPLEMENTED];
  // The Factor was successfully verified.
  VERIFICATION_SUCCEEDED = 1;
  // The Factor cannot be verified without additional steps. The response will contain a challenge to verify the Factor
  // successfully.
  VERIFICATION_CHALLENGE = 2;
  // The Factor cannot be verified.
  VERIFICATION_FAILED = 3;
}

message PushChallengeData {
    option (.wix.api.decomposite_of) = "wix.iam.authentication.factor.v1.PushChallengeData";
  // This should be tied to a specific push notification.
  // It will be sent in subsequent requests to verify the factor.
  string transaction_id = 1 [(.wix.api.maxLength) = 36];
}

message WebAuthnChallengeData {
    option (.wix.api.decomposite_of) = "wix.iam.authentication.factor.v1.WebAuthnChallengeData";
  // A unique identifier for this challenge that will be used to correlate 
  // the authentication response with this challenge.
  // This should be a cryptographically random GUID to prevent guessing attacks.
  string challenge_id = 1 [(.wix.api.format) = GUID];

  // The challenge that will be signed by the authenticator during the WebAuthn authentication ceremony.
  // This should be a cryptographically secure random value with at least 16 bytes of entropy.
  // The value is used to prevent replay attacks and MUST be randomly generated by the implementer.
  bytes challenge = 2;
  
  // The timeout in milliseconds for the WebAuthn authentication ceremony.
  // After this time, the challenge will be considered expired and the authentication will need to be restarted.
  // This is optional and may be overridden by the client if provided.
  // The WebAuthn spec recommends a timeout of at least 1 minute (60000ms).
  google.protobuf.Int32Value timeout_ms = 3;
  
  // Optional list of credentials that are acceptable for this authentication ceremony.
  // If empty, all credentials associated with the user will be considered.
  repeated PublicKeyCredentialDescriptor allow_credentials = 4 [(.wix.api.maxSize) = 50];
  
  // Specifies the requirement for user verification during the authentication ceremony.
  UserVerificationRequirement user_verification = 5;
  
  // Optional hints to guide the client UI
  // Examples include "security-key" to emphasize external authenticators
  // or "client-device" to emphasize built-in authenticators
  repeated string hints = 6 [(.wix.api.maxLength) = 50, (.wix.api.maxSize) = 10];

  message AuthenticationExtensionInputs {
        option (.wix.api.decomposite_of) = "wix.iam.authentication.factor.v1.WebAuthnChallengeData.AuthenticationExtensionInputs";
    // FIDO AppID Extension (appid)
    // An AppID that was used for previously registered U2F authenticators
    // This makes already-registered U2F credentials forward-compatible with the WebAuthn API
    string appid = 1 [(.wix.api.maxLength) = 256];
    
    // Large Blob Storage Extension (largeBlob)
    // Controls access to the authenticator's large blob storage
    oneof large_blob_operation {
      // Read existing large blob data from the authenticator
      bool large_blob_read = 2;
      // Write data to the authenticator's large blob storage
      bytes large_blob_write = 3;
    }
    
    // User Verification Method Extension (uvm)
    // Requests the authenticator to report which verification methods were used
    // Examples include fingerprint, PIN, or facial recognition
    bool uvm = 4;
  }
  // Optional extensions for the authentication ceremony
  // Provides additional parameters for specialized WebAuthn functionality
  AuthenticationExtensionInputs extensions = 7;
}

message VerificationChallenge {
    option (.wix.api.decomposite_of) = "wix.iam.authentication.factor.v1.VerificationChallenge";
  google.protobuf.StringValue hint = 1 [(.wix.api.maxLength) = 200];
  oneof factor_challenge_data {
    PushChallengeData push_data = 2;
    WebAuthnChallengeData webauthn_data = 3;
  }
}

enum VerificationFailedReason {
  UNKNOWN_VERIFICATION_FAILED_REASON = 0 [(.wix.api.enum_maturity) = NOT_IMPLEMENTED];
  // The factor could not be verified because the provided factor data was incorrect.
  INCORRECT_FACTOR_DATA = 1;
  // The factor could not be verified because the provided factor data has expired.
  EXPIRED_FACTOR_DATA = 2;
  // The factor could not be verified because the provided factor data has been used before.
  REPLAYED_FACTOR_DATA = 3;
  // The factor data was invalidated by the user, eg. by cancelling the verification process.
  INVALIDATED_FACTOR_DATA = 4;
  // The factor could not be verified because it requires re-enrollment (eg. due to leaked credentials).
  REENROLLMENT_REQUIRED = 5;
}

enum EnrollmentFailedReason {
  UNKNOWN_ENROLLMENT_FAILED_REASON = 0 [(.wix.api.enum_maturity) = NOT_IMPLEMENTED];
  // The factor could not be enrolled because the provided factor data was incorrect (eg. the passkey credential did not match the challenge or was signed incorrectly).
  INCORRECT_ENROLLMENT_DATA = 1;
  // The factor could not be enrolled because the provided factor data has expired.
  EXPIRED_ENROLLMENT_DATA = 2;
  // The factor could not be enrolled because the provided factor data has been used before.
  REPLAYED_ENROLLMENT_DATA = 3;
  // The enrollment data was invalidated by the user, eg. by cancelling the enrollment process.
  INVALIDATED_ENROLLMENT_DATA = 4;
  // The factor could not be enrolled because it violates enrollment policy (e.g. the provided password was too short, the passkey credential used an unapproved authenticator type).
  ENROLLMENT_POLICY_VIOLATION = 5;
}

message VerificationFailed {
    option (.wix.api.decomposite_of) = "wix.iam.authentication.factor.v1.VerificationFailed";
  // The reason for the verification failure.
  VerificationFailedReason reason = 1;
  // A human-readable message describing the reason for the failure. This is used for logging and debugging purposes.
  string message = 2 [(.wix.api.maxLength) = 200];
  // Optional error data to be sent to the client as-is, alongside the reason.
  google.protobuf.Struct error_data = 3 [(.wix.api.field_exposure) = PRIVATE];
}

message EnrollmentFailed {
    option (.wix.api.decomposite_of) = "wix.iam.authentication.factor.v1.EnrollmentFailed";
  // The reason for the enrollment failure.
  EnrollmentFailedReason reason = 1;
  // A human-readable message describing the reason for the failure. This is used for logging and debugging purposes.
  string message = 2 [(.wix.api.maxLength) = 200];
  // Optional error data to be sent to the client as-is, alongside the reason.
  google.protobuf.Struct error_data = 3 [(.wix.api.field_exposure) = PRIVATE];
}

message VerificationSucceeded {
    option (.wix.api.decomposite_of) = "wix.iam.authentication.factor.v1.VerificationSucceeded";
  // The identity_id of the user that was authenticated.
  // This MUST be set when verification succeeds for WebAuthn passkey authentication
  // that started without an identity_id.
  // For other authentication flows where the identity_id was provided in the request,
  // this field is optional.
  google.protobuf.StringValue identity_id = 1 [(.wix.api.format) = GUID];
}

message VerifyResponse {
    option (.wix.api.decomposite_of) = "wix.iam.authentication.factor.v1.VerifyResponse";
  VerificationStatus verification_status = 1;
  oneof verification_result {
    option (.wix.api.aligned_with_enum) = {
      field: "verification_status";
      suffix: "data";
    };
    VerificationSucceeded verification_succeeded_data = 4;
    VerificationChallenge verification_challenge_data = 2;
    VerificationFailed verification_failed_data = 3;
  }
}

// flynt-disable deleted-field-enum-reserved
message ValidateRequest {
    option (.wix.api.decomposite_of) = "wix.iam.authentication.factor.v1.ValidateRequest";
  FactorType factor_type = 1;
  oneof factor_data {
    option (.wix.api.aligned_with_enum) = {
      field: "factor_type";
      suffix: "data";
    };
    PasswordData password_data = 2;
  }
}

message ValidateResponse {
  option (.wix.api.decomposite_of) = "wix.iam.authentication.factor.v1.ValidateResponse";
}

// A common structure containing WebAuthn credential information
message WebAuthnCredentialInfo {
        option (.wix.api.decomposite_of) = "wix.iam.authentication.factor.v1.ValidateResponse.WebAuthnCredentialInfo";
  // Unique identifier for the credential
  // This is the credential ID that can be used for future authentications
  bytes credential_id = 1;
  
  // Whether the credential is resident (client-side discoverable)
  // Indicates if this is a passkey that can be used for passwordless authentication
  bool resident_key = 2;
  
  // Whether user verification was performed during registration
  // Indicates if this credential uses biometrics, PIN, or other user verification method
  bool user_verified = 3;
  
  // Whether the credential supports backup (syncing across devices)
  bool backup_eligible = 4;
  
  // Whether the credential is currently backed up (synced to the cloud)
  bool backed_up = 5;
  
  // A user-readable name for the authenticator device (eg. iCloud Keychain, Windows Hello, etc.), 
  // likely derived from the authenticator's AAGUID.
  string authenticator_name = 6 [(.wix.api.maxLength) = 100];

  // Create date of the enrollment of the credential
  google.protobuf.Timestamp created_date = 7;

  // Last successful verification date of the credential
  google.protobuf.Timestamp last_used_date = 8;
}

enum UserVerificationRequirement {
  // Default unspecified value
  USER_VERIFICATION_UNSPECIFIED = 0;
  // The Relying Party requires user verification and will fail the operation if the response doesn't have the UV flag
  // set
  USER_VERIFICATION_REQUIRED = 1;
  // The Relying Party prefers user verification but will not fail the operation if unavailable
  USER_VERIFICATION_PREFERRED = 2;
  // The Relying Party does not want user verification employed (e.g., to minimize disruption to the user experience)
  USER_VERIFICATION_DISCOURAGED = 3;
}

message PublicKeyCredentialDescriptor {
    option (.wix.api.decomposite_of) = "wix.iam.authentication.factor.v1.PublicKeyCredentialDescriptor";
  // The credential ID
  bytes id = 1;
  // An optional hint as to the transports used by the credential
  // Examples include "usb", "nfc", "ble", "internal", "hybrid"
  repeated string transports = 2 [(.wix.api.maxLength) = 50, (.wix.api.maxSize) = 10];
}

enum COSEAlgorithmIdentifier {
  // Default unspecified value
  ALGORITHM_UNSPECIFIED = 0;
  // ECDSA with SHA-256 (COSE value = -7)
  ES256 = 1;
  // EdDSA (COSE value = -8)
  EDDSA = 2;
  // ECDSA with SHA-384 (COSE value = -35)
  ES384 = 3;
  // ECDSA with SHA-512 (COSE value = -36)
  ES512 = 4;
  // RSASSA-PKCS1-v1_5 using SHA-256 (COSE value = -257)
  RS256 = 5;
  // RSASSA-PKCS1-v1_5 using SHA-384 (COSE value = -258)
  RS384 = 6;
  // RSASSA-PKCS1-v1_5 using SHA-512 (COSE value = -259)
  RS512 = 7;
}

message UnenrollRequest {
    option (.wix.api.decomposite_of) = "wix.iam.authentication.factor.v1.UnenrollRequest";
  // The identity ID associated with the factor
  string identity_id = 1 [(.wix.api.format) = GUID];
  
  // The type of factor to unenroll
  FactorType factor_type = 2;
  
  // specifier to target a specific factor instance
  // Required for factor types that support multiple instances per identity (e.g., WebAuthn)
  oneof factor_specifier {
    option (.wix.api.aligned_with_enum) = {
      field: "factor_type";
      suffix: "specifier";
    };
    WebAuthnSpecifier webauthn_specifier = 3;
  }
}

message UnenrollResponse {
    option (.wix.api.decomposite_of) = "wix.iam.authentication.factor.v1.UnenrollResponse";
  // The factor type that was unenrolled
  FactorType factor_type = 1;

  // Updated factor information after unenrollment
  // Returns the remaining active factors for the identity
  oneof factor_data {
    option (.wix.api.aligned_with_enum) = {
      field: "factor_type";
      suffix: "data";
    };
    WebAuthnGetData webauthn_data = 2;
    PushGetData push_data = 3;
    TotpGetData totp_data = 4;
    RecoveryCodeGetData recovery_code_data = 5;
  }
}

message WebAuthnSpecifier {
    option (.wix.api.decomposite_of) = "wix.iam.authentication.factor.v1.WebAuthnSpecifier";
    // WebAuthn credential ID for targeting specific WebAuthn credentials
  bytes webauthn_credential_id = 1;
}

message GetRequest {
    option (.wix.api.decomposite_of) = "wix.iam.authentication.factor.v1.GetRequest";
  // The identity ID associated with the factor
  string identity_id = 1 [(.wix.api.format) = GUID];
}

message GetResponse {
    option (.wix.api.decomposite_of) = "wix.iam.authentication.factor.v1.GetResponse";
  FactorType factor_type = 1;

  // Factor-specific information
  oneof factor_data {
    option (.wix.api.aligned_with_enum) = {
      field: "factor_type";
      suffix: "data";
    };
    WebAuthnGetData webauthn_data = 2;
    PushGetData push_data = 3;
    TotpGetData totp_data = 4;
    RecoveryCodeGetData recovery_code_data = 5;
  }
}

message WebAuthnGetData {
    option (.wix.api.decomposite_of) = "wix.iam.authentication.factor.v1.WebAuthnGetData";
  // List of credential infos for a given identityId
  repeated WebAuthnCredentialInfo credentials = 1 [(.wix.api.maxSize) = 10];
}

message PushGetData {
    option (.wix.api.decomposite_of) = "wix.iam.authentication.factor.v1.PushGetData";
  // The name of the application
  string app_name = 1 [(.wix.api.maxLength) = 50];

  // The unique device/installation identifier
  string device_id = 2 [(.wix.api.maxLength) = 180, (.wix.api.format) = GUID];

  // Device information containing brand and model details
  PushDeviceInfo device_info = 3;
}

message PushDeviceInfo {
    option (.wix.api.decomposite_of) = "wix.iam.authentication.factor.v1.PushDeviceInfo";
  // The brand name of the device (e.g., "google")
  string brand_name = 1 [(.wix.api.maxLength) = 50];

  // The model name of the device (e.g., "Pixel 7 Pro")
  string model_name = 2 [(.wix.api.maxLength) = 50];
}
message TotpGetData {
    option (.wix.api.decomposite_of) = "wix.iam.authentication.factor.v1.TotpGetData";
  // A user-friendly identifier that helps users recognize which account or service
  // the TOTP code is associated with (e.g., "Wix:john.doe@gmail.com").
  string label = 1 [(.wix.api.maxLength) = 100];
}

message RecoveryCodeGetData {
    option (.wix.api.decomposite_of) = "wix.iam.authentication.factor.v1.RecoveryCodeGetData";
  google.protobuf.Timestamp codes_generated_date = 1;
}


message FactorConfig {
  option (.wix.api.decomposite_of) = "wix.iam.authentication.factor.v1.FactorConfig";
  // the base URI where all the methods are deployed.
   .wix.common.spi.SpiBaseUri uri_config = 1;
  // the type of the factor
  FactorType factor_type = 2;
  // whether the factor supports verify without enrolling first
  bool supports_verify_without_enroll = 3;
  // whether the factor implementer requires enrollment
  bool enroll_required = 4;
}
