diff --git a/proto/ivms101/enum.proto b/proto/ivms101/enum.proto new file mode 100644 index 0000000..9d25962 --- /dev/null +++ b/proto/ivms101/enum.proto @@ -0,0 +1,206 @@ +// Specification Copyright (c) 2020 Joint Working Group on interVASP Messaging Standards +// https://intervasp.org/ +// https://intervasp.org/wp-content/uploads/2020/05/IVMS101-interVASP-data-model-standard-issue-1-FINAL.pdf + +// Protocol Buffer Specification Copyright (c) 2020 CipherTrace, Inc. https://ciphertrace.com + +// Licensed under MIT License + +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: + +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. + +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +// NOTE ON THE SPECIFICATION MAPPING +// This protocol buffers specification has applied the Protocol Buffers style guide +// https://developers.google.com/protocol-buffers/docs/style to the ISVM101 +// specification to be consistent with other Protocol Buffers specifications and to +// avoid common pitfalls when generating language specific classes. + +syntax = "proto3"; + +package ivms101; +option go_package = "github.com/trisacrypto/testnet/pkg/ivms101"; + + +/*************************************************** + * Data Types ENUMS + ***************************************************/ + + // Definition: A single value corresponding to the nature of name being adopted. + enum NaturalPersonNameTypeCode { + + // Alias name + // A name other than the legal name by which a natural person is also known. + NATURAL_PERSON_NAME_TYPE_CODE_ALIA = 0; + + // Name at birth + // The name given to a natural person at birth. + NATURAL_PERSON_NAME_TYPE_CODE_BIRT = 1; + + // Maiden name + // The original name of a natural person who has changed their name after marriage. + NATURAL_PERSON_NAME_TYPE_CODE_MAID = 2; + + // Legal name + // Identifies a natural person for legal, official or administrative purposes. + NATURAL_PERSON_NAME_TYPE_CODE_LEGL = 3; + + // Unspecified + // A name by which a natural person may be known but which cannot otherwise be + // categorized or the category of which the sender is unable to determine. + NATURAL_PERSON_NAME_TYPE_CODE_MISC = 4; + } + +// Definition: A single value corresponding to the nature of name being specified +// for the legal person. +enum LegalPersonNameTypeCode { + // Legal name + // Official name under which an organisation is registered. + LEGAL_PERSON_NAME_TYPE_CODE_LEGL = 0; + + // Short name + // Specifies the short name of the organisation. + LEGAL_PERSON_NAME_TYPE_CODE_SHRT = 1; + + // Trading name + // Name used by a business for commercial purposes, although its registered legal + // name, used for contracts and other formal situations, may be another. + LEGAL_PERSON_NAME_TYPE_CODE_TRAD = 2; +} + +// Definition: Identifies the nature of the address. +enum AddressTypeCode { + + // Residential + // Address is the home address. + ADDRESS_TYPE_CODE_HOME = 0; + + // Business + // Address is the business address. + ADDRESS_TYPE_CODE_BIZZ = 1; + + // Geographic + // Address is the unspecified physical (geographical) address suitable for + // identification of the natural or legal person. + ADDRESS_TYPE_CODE_GEOG = 2; +} + +// Definition: Identifies the national identification type. +// NationalIdentifierTypeCode applies a restriction over the codes present in ISO20022 +// datatype ‘TypeOfIdentification4Code’. +enum NationalIdentifierTypeCode { + + // Alien registration number + // Number assigned by a government agency to identify foreign nationals. + NATIONAL_IDENTIFIER_TYPE_CODE_ARNU = 0; + + // Passport number + // Number assigned by a passport authority. + NATIONAL_IDENTIFIER_TYPE_CODE_CCPT = 1; + + // Registration authority identifier + // Identifier of a legal entity as maintained by a registration authority. + NATIONAL_IDENTIFIER_TYPE_CODE_RAID = 2; + + // Driver license number + // Number assigned to a driver's license. + NATIONAL_IDENTIFIER_TYPE_CODE_DRLC = 3; + + // Foreign investment identity number + // Number assigned to a foreign investor (other than the alien number). + NATIONAL_IDENTIFIER_TYPE_CODE_FIIN = 4; + + // Tax identification number + // Number assigned by a tax authority to an entity. + NATIONAL_IDENTIFIER_TYPE_CODE_TXID = 5; + + // Social security number + // Number assigned by a social security agency. + NATIONAL_IDENTIFIER_TYPE_CODE_SOCS = 6; + + // Identity card number + // Number assigned by a national authority to an identity card. + NATIONAL_IDENTIFIER_TYPE_CODE_IDCD = 7; + + // Legal Entity Identifier + // Legal Entity Identifier (LEI) assigned in accordance with ISO 17442. + // The LEI is a 20-character, alpha-numeric code that enables clear and unique + // identification of legal entities participating in financial transactions. + NATIONAL_IDENTIFIER_TYPE_CODE_LEIX = 8; + + // Unspecified + // A national identifier which may be known but which cannot otherwise be + // categorized or the category of which the sender is unable to determine. + NATIONAL_IDENTIFIER_TYPE_CODE_MISC = 9; +} + +// Definition: Identifies the national script from which transliteration to Latin +// script is applied. +enum TransliterationMethodCode { + + // Arabic (Arabic language) + // ISO 233-2:1993 + TRANSLITERATION_METHOD_CODE_ARAB = 0; + + // Arabic (Persian language) + // ISO 233-3:1999 + TRANSLITERATION_METHOD_CODE_ARAN = 1; + + // Armenian + // ISO 9985:1996 + TRANSLITERATION_METHOD_CODE_ARMN = 2; + + // Cyrillic + // ISO 9:1995 + TRANSLITERATION_METHOD_CODE_CYRL = 3; + + // Devanagari & related Indic + // ISO 15919:2001 + TRANSLITERATION_METHOD_CODE_DEVA = 4; + + // Georgian + // ISO 9984:1996 + TRANSLITERATION_METHOD_CODE_GEOR = 5; + + // Greek + // ISO 843:1997 + TRANSLITERATION_METHOD_CODE_GREK = 6; + + // Han (Hanzi, Kanji, Hanja) + // ISO 7098:2015 + TRANSLITERATION_METHOD_CODE_HANI = 7; + + // Hebrew + // ISO 259-2:1994 + TRANSLITERATION_METHOD_CODE_HEBR = 8; + + // Kana + // ISO 3602:1989 + TRANSLITERATION_METHOD_CODE_KANA = 10; + + // Korean + // Revised Romanization of Korean + TRANSLITERATION_METHOD_CODE_KORE = 11; + + // Thai + // ISO 11940-2:2007 + TRANSLITERATION_METHOD_CODE_THAI = 12; + + // Script other than those listed above + // Unspecified Standard + TRANSLITERATION_METHOD_CODE_OTHR = 13; +} \ No newline at end of file diff --git a/proto/ivms101/identity.proto b/proto/ivms101/identity.proto new file mode 100644 index 0000000..9f35ae4 --- /dev/null +++ b/proto/ivms101/identity.proto @@ -0,0 +1,132 @@ +// Specification Copyright (c) 2020 Joint Working Group on interVASP Messaging Standards +// https://intervasp.org/ +// https://intervasp.org/wp-content/uploads/2020/05/IVMS101-interVASP-data-model-standard-issue-1-FINAL.pdf + +// Protocol Buffer Specification Copyright (c) 2020 CipherTrace, Inc. https://ciphertrace.com + +// Licensed under MIT License + +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: + +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. + +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +// NOTE ON THE SPECIFICATION MAPPING +// This protocol buffers specification has applied the Protocol Buffers style guide +// https://developers.google.com/protocol-buffers/docs/style to the ISVM101 +// specification to be consistent with other Protocol Buffers specifications and to +// avoid common pitfalls when generating language specific classes. + +syntax = "proto3"; + +package ivms101; +option go_package = "github.com/trisacrypto/testnet/pkg/ivms101"; + +import "ivms101/ivms101.proto"; +import "ivms101/enum.proto"; + + +/*************************************************************************** + * Top Level Model (not formally described in IVMS101, only examples) + ***************************************************************************/ + +message IdentityPayload { + Originator originator = 1; + Beneficiary beneficiary = 2; + OriginatingVasp originating_vasp = 3; + BeneficiaryVasp beneficiary_vasp = 4; + TransferPath transfer_path = 5; + PayloadMetadata payload_metadata = 6; +} + + +message Originator { + + // Definition: the account holder who allows the VA transfer from that account or, + // where there is no account, the natural or legal person that places the order with + // the originating VASP to perform the VA transfer. + // One or More + repeated Person originator_persons = 1; + + // Definition: Identifier of an account that is used to process the transaction. + // The value for this element is case-sensitive. + // Datatype: “Max100Text” + // Zero or More + repeated string account_numbers = 2; +} + +message Beneficiary { + + // Definition: the natural or legal person or legal arrangement who is identified + // by the originator as the receiver of the requested VA transfer. + // One or More + repeated Person beneficiary_persons = 1; + + // Definition: Identifier of an account that is used to process the transaction. + // The value for this element is case-sensitive. + // Datatype: “Max100Text” + // Zero or More + repeated string account_numbers = 2; +} + +message OriginatingVasp { + + // Definition: refers to the VASP which initiates the VA transfer, and transfers + // the VA upon receiving the request for a VA transfer on behalf of the originator. + // Optional + Person originating_vasp = 1; +} + +message BeneficiaryVasp { + + // Definition: the VASP which receives the transfer of a virtual asset from the + // originating VASP directly or through an intermediary VASP and makes the funds + // available to the beneficiary. + // Optional + Person beneficiary_vasp = 1; +} + +message IntermediaryVasp { + + // Definition: the VASP in a serial chain that receives and retransmits a VA + // transfer on behalf of the originating VASP and the beneficiary VASP, or another + // intermediary VASP. + // Required + Person intermediary_vasp = 1; + + // Definition: the sequence in a serial chain at which the corresponding + // intermediary VASP participates in the transfer. + // Constraints: totalDigits: 18; fractionDigits: 0 + // Required + uint64 sequence = 2; +} + +message TransferPath { + + // Definition: the intermediary VASP(s) participating in a serial chain that + // receive and retransmit a VA transfer on behalf of the originating VASP and the + // beneficiary VASP, or another intermediary VASP, together with their + // corresponding sequence number. + // Zero or More + repeated IntermediaryVasp transfer_path = 1; +} + +message PayloadMetadata { + + // Definition: the method used to map from a national system of writing to Latin script. + // Zero or More + repeated TransliterationMethodCode transliteration_method = 1; +} diff --git a/proto/ivms101/ivms101.proto b/proto/ivms101/ivms101.proto new file mode 100644 index 0000000..7fbaf79 --- /dev/null +++ b/proto/ivms101/ivms101.proto @@ -0,0 +1,387 @@ +// Specification Copyright (c) 2020 Joint Working Group on interVASP Messaging Standards +// https://intervasp.org/ +// https://intervasp.org/wp-content/uploads/2020/05/IVMS101-interVASP-data-model-standard-issue-1-FINAL.pdf + +// Protocol Buffer Specification Copyright (c) 2020 CipherTrace, Inc. https://ciphertrace.com + +// Licensed under MIT License + +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: + +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. + +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +// NOTE ON THE SPECIFICATION MAPPING +// This protocol buffers specification has applied the Protocol Buffers style guide +// https://developers.google.com/protocol-buffers/docs/style to the ISVM101 +// specification to be consistent with other Protocol Buffers specifications and to +// avoid common pitfalls when generating language specific classes. + +syntax = "proto3"; + +package ivms101; +option go_package = "github.com/trisacrypto/testnet/pkg/ivms101"; + +import "ivms101/enum.proto"; + + +/*************************************************** + * Data Types Components + ***************************************************/ + +message Person { + + oneof person { + + // Definition: a uniquely distinguishable individual; one single person. + NaturalPerson natural_person = 1; + + // Definition: any entity other than a natural person that can establish a + // permanent customer relationship with an affected entity or otherwise own + // property. This can include companies, bodies corporate, foundations, anstalt, + // partnerships, or associations and other relevantly similar entities. + LegalPerson legal_person = 2; + } + +} + +// Definition: refers to a uniquely distinguishable individual; one single person +message NaturalPerson { + + // Definition: the distinct words used as identification for an individual. + // Required + NaturalPersonName name = 1; + + // Definition: the particulars of a location at which a person may be communicated with. + // Zero or More + repeated Address geographic_addresses = 2; + + // Definition: a distinct identifier used by governments of countries to uniquely + // identify a natural or legal person. + // Optional + NationalIdentification national_identification = 3; + + // Definition: a distinct identifier that uniquely identifies the person to the + // institution in context. + // Datatype: “Max50Text” + // Optional + string customer_identification = 4; + + // Definition: date and place of birth of a person. + // Optional + DateAndPlaceOfBirth date_and_place_of_birth = 5; + + // Definition: country in which a person resides (the place of a person's home). + // The value used for the field country must be present on the ISO-3166-1 alpha-2 + // codes or the value XX. + // Datatype: “CountryCode” + // Optional + string country_of_residence = 6; +} + +message NaturalPersonName { + + // At least one occurrence of naturalPersonNameID must have the value ‘LEGL’ + // specified in the element naturalPersonNameIdentifierType. + // Definition: full name separated into primary and secondary identifier. + // One or more + repeated NaturalPersonNameId name_identifiers = 1; + + // Definition: full name separated into primary and secondary identifier using + // local characters. + // Zero or more + repeated LocalNaturalPersonNameId local_name_identifiers = 2; + + // Definition: Alternate representation of a name that corresponds to the manner + // the name is pronounced. + // Zero or more + repeated LocalNaturalPersonNameId phonetic_name_identifiers = 3; +} + +message NaturalPersonNameId { + + // Definition: This may be the family name, the maiden name or the married name, + // the main name, the surname, and in some cases, the entire name where the natural + // person’s name cannot be divided into two parts, or where the sender is unable to + // divide the natural person’s name into two parts. + // Datatype: “Max100Text” + // Required + string primary_identifier = 1; + + // Definition: These may be the forenames, familiar names, given names, initials, + // prefixes, suffixes or Roman numerals (where considered to be legally part of the + // name) or any other secondary names. + // Datatype: “Max100Text” + // Optional + string secondary_identifier = 2; + + // Definition: The nature of the name specified. + // Required + NaturalPersonNameTypeCode name_identifier_type = 3; +} + +message LocalNaturalPersonNameId { + + // Definition: This may be the family name, the maiden name or the married name, + // the main name, the surname, and in some cases, the entire name where the natural + // person’s name cannot be divided into two parts, or where the sender is unable to + // divide the natural person’s name into two parts. + // Datatype: “LocalMax100Text” + // Required + string primary_identifier = 1; + + // Definition: These may be the forenames, familiar names, given names, initials, + // prefixes, suffixes or Roman numerals (where considered to be legally part of + // the name) or any other secondary names. + // Datatype: “LocalMax100Text” + // Optional + string secondary_identifier = 2; + + // Definition: The nature of the name specified. + // Required + NaturalPersonNameTypeCode name_identifier_type = 3; +} + +// Constraint: ValidAddress +// There must be at least one occurrence of the element addressLine or (streetName and +// buildingName and/or buildingNumber). +message Address { + + // Definition: Identifies the nature of the address. + // Required + AddressTypeCode address_type = 1; + + // Definition: Identification of a division of a large organisation or building. + // Datatype: “Max50Text” + // Optional + string department = 2; + + // Definition: Identification of a sub-division of a large organisation or building. + // Datatype: “Max70Text” + // Optional + string sub_department = 3; + + // Definition: Name of a street or thoroughfare. + // Datatype: “Max70Text” + // Optional + string street_name = 4; + + // Definition: Number that identifies the position of a building on a street. + // Datatype: “Max16Text” + // Optional + string building_number = 5; + + // Definition: Name of the building or house. + // Datatype: “Max35Text” + // Optional + string building_name = 6; + + // Definition: Floor or storey within a building. + // Datatype: “Max70Text” + // Optional + string floor = 7; + + // Definition: Numbered box in a post office, assigned to a person or organisation, + // where letters are kept until called for. + // Datatype: “Max16Text” + // Optional + string post_box = 8; + + // Definition: Building room number. + // Datatype: “Max70Text” + // Optional + string room = 9; + + // Definition: Identifier consisting of a group of letters and/or numbers that is + // added to a postal address to assist the sorting of mail. + // Datatype: “Max16Text” + // Optional + string post_code = 10; + + // Definition: Name of a built-up area, with defined boundaries and a local government. + // Datatype: “Max35Text” + // Optional + string town_name = 11; + + // Definition: Specific location name within the town. + // Datatype: “Max35Text” + // Optional + string town_location_name = 12; + + // Definition: Identifies a subdivision within a country subdivision. + // Datatype: “Max35Text” + // Optional + string district_name = 13; + + // Definition: Identifies a subdivision of a country for example, state, region, + // province, départment or county. + // Datatype: “Max35Text” + // Optional + string country_sub_division = 14; + + // Definition: Information that locates and identifies a specific address, as + // defined by postal services, presented in free format text. + // Datatype: “Max70Text” + // Zero to Seven + repeated string address_line = 15; + + // Constraint: The value used for the field country must be present on the + // ISO-3166-1 alpha-2 codes or the value XX. + // Datatype: “CountryCode” + // Required + string country = 16; +} + +// Constraint: DateInPast +// If dateOfBirth is specified, the date specified must be a historic date (i.e. a date +// prior to the current date) +message DateAndPlaceOfBirth { + + // Definition: Date on which a person is born. + // Definition: A point in time, represented as a day within the calendar year. + // Compliant with ISO 8601. + // Type: Text + // Format: YYYY-MM-DD + // Regex: ^([0-9]{4})-([0-9]{2})-([0-9]{2})$ + // Required + string date_of_birth = 1; + + // Definition: The town and/or the city and/or the suburb and/or the country + // subdivision and/or the country where the person was born. + // Datatype: “Max70Text” + // Required + string place_of_birth = 2; +} + + +// Constraint: ValidNationalIdentifierLegalPerson +// A legal person must have a value for nationalIdentifierType of either ‘RAID’ or +// ‘MISC’ or ‘LEIX’ or ‘TXID’. +// Constraint: CompleteNationalIdentifierLegalPerson +// A LegalPerson must not have a value for countryOfIssue and must have a value for the +// element RegistrationAuthority if the value for nationalIdentifierType is not ‘LEIX’ +// Constraint: ValidLEI +// A LegalPerson with a nationalIdentifierType of ‘LEIX’ must have a value for the +// element nationalIdentifier that adheres to the convention as stated in datatype +// ‘LEIText’. +message NationalIdentification { + + // Definition: An identifier issued by an appropriate issuing authority. + // Constraint: ValidLEI + // Datatype: “Max35Text” + // Required + string national_identifier = 1; + + // Definition: Specifies the type of identifier specified. + // Required + NationalIdentifierTypeCode national_identifier_type = 2; + + // Definition: Country of the issuing authority. + // Datatype: “CountryCode” + // Optional + string country_of_issue = 3; + + // Definition: A code specifying the registration authority. + // Constraint: The value used for the applicable element must be present on the + // GLEIF Registration Authorities List. + // Datatype: “RegistrationAuthority” + // Optional + string registration_authority = 4; +} + +// Definition: refers to any entity other than a natural person that can establish a +// permanent customer relationship with an affected entity or otherwise own property. +// This can include companies, bodies corporate, foundations, anstalt, partnerships, or +// associations and other relevantly similar entities. +// Constraint: OriginatorInformationLegalPerson +// If the originator is a LegalPerson either geographicAddress (with an addressType +// value of ‘GEOG’) and/or nationalIdentification and/or customerNumber is required. +message LegalPerson { + + // Definition: The name of the legal person. + // Constraint: LegalNamePresentLegalPerson + // At least one occurrence of legalPersonNameIdentifier must have the value ‘LEGL’ + // specified in the element legalPersonNameIdentifierType. + LegalPersonName name = 1; + + // Definition: The address of the legal person. + // Zero or more + repeated Address geographic_addresses = 2; + + // Definition: The unique identification number applied by the VASP to customer. + // NOTE The specification has a descrepency in that 5.2.9.3.3 specifies an element + // name as "customerNumber", while the table in 5.2.9.1 calls that element + // "customerIdentification" + // Datatype: “Max50Text” + // Optional + string customer_number = 3; + + // Definition: A distinct identifier used by governments of countries to uniquely + // identify a natural or legal person. + // Optional + NationalIdentification national_identification = 4; + + // Definition: The country in which the legal person is registered. + // Constraint: The value used for the field country must be present on the + // ISO-3166-1 alpha-2 codes or the value XX. + // Datatype: “CountryCode” + // Optional + string country_of_registration = 5; +} + +message LegalPersonName { + + // Definition: The name and type of name by which the legal person is known. + // Constraint: LegalNamePresent + // At least one occurrence of legalPersonNameIdentifier must have the value + // ‘LEGL’ specified in the element legalPersonNameIdentifierType. + // One or more + repeated LegalPersonNameId name_identifiers = 1; + + // Definition: The name and type of name by which the legal person is known using + // local characters. + // Zero or more + repeated LocalLegalPersonNameId local_name_identifiers = 2; + + // Definition: The name and type of name by which the legal person is known using + // local characters. + // Zero or more + repeated LocalLegalPersonNameId phonetic_name_identifiers = 3; +} + +message LegalPersonNameId { + + // Definition: Name by which the legal person is known. + // Datatype: “Max100Text” + // Required + string legal_person_name = 1; + + // Definition: The nature of the name specified. + // Required + LegalPersonNameTypeCode legal_person_name_identifier_type = 2; +} + +message LocalLegalPersonNameId { + + // Definition: Name by which the legal person is known. + // Datatype: "LocalMax100Text" + // Required + string legal_person_name = 1; + + // Definition: The nature of the name specified. + // Required + LegalPersonNameTypeCode legal_person_name_identifier_type = 2; +} \ No newline at end of file diff --git a/proto/trisa/api/v1alpha1/trisa.proto b/proto/trisa/api/v1alpha1/trisa.proto new file mode 100644 index 0000000..7a68d0c --- /dev/null +++ b/proto/trisa/api/v1alpha1/trisa.proto @@ -0,0 +1,45 @@ +syntax = "proto3"; + +package trisa.protocol.v1alpha1; + +import "google/protobuf/any.proto"; + +option go_package = "github.com/trisacrypto/trisa/proto/trisa/protocol/v1alpha1"; + +service TrisaPeer2Peer { + rpc TransactionStream(stream Transaction) returns (stream Transaction) {} +} + +message Transaction { + // The transaction identifier generated by the sender. Any response + // to a transaction request needs to carry the same identifier. + string id = 1; + + // Encrypted TransactionData + bytes transaction = 2; + + // Encryption key used to encrypt the transaction blob. This key itself + // is encrypted using the public key of the receiver. + bytes encryption_key = 3; + + // The encryption algorithm used to encrypt the transaction blob. + string encryption_algorithm = 4; + + // HMAC signature calculated from encrypted transaction blob. + bytes hmac = 5; + + // The HMAC secret used to calculate the HMAC signature. This secret + // itself is encrypted using the public key of the receiver. + bytes hmac_secret = 6; + + // The algorithm used to calculate the HMAC signature. + string hmac_algorithm = 7; +} + +message TransactionData { + // Identity contains any valid identity structure. + google.protobuf.Any identity = 1; + + // Data contains the network specific data. + google.protobuf.Any data = 2; +} diff --git a/proto/trisa/api/v1beta1/api.proto b/proto/trisa/api/v1beta1/api.proto new file mode 100644 index 0000000..f4de173 --- /dev/null +++ b/proto/trisa/api/v1beta1/api.proto @@ -0,0 +1,158 @@ +syntax = "proto3"; + +package trisa.api.v1beta1; +option go_package = "github.com/trisacrypto/trisa/pkg/trisa/api/v1beta1;api"; + +import "google/protobuf/any.proto"; +import "trisa/api/v1beta1/errors.proto"; + + +// The TRISANetwork service defines the peer-to-peer interactions between VASPs that are +// necessary to conduct compliance information exchanges. All TRISA members must +// implement all services described by the TRISA protocol to ensure that exchanges are +// conducted correctly and securely. The primary RPCs are Transfer and TransactionStream +// which allow VASPs to exchange compliance information before conducting a virtual +// asset transaction. The other RPCs facilitate Transfers, allowing address +// confirmations prior to a transfer and public key exchange so that transaction +// envelopes can be encrypted and signed. +service TRISANetwork { + // To conduct an information exchange prior to a virtual asset transaction, an + // originating VASP will send an encrypted transaction envelope to the beneficiary + // VASP containing a unique ID for the transaction, the encrypted transaction bundle, + // and metadata associated with the transaction cipher. In response, the beneficiary + // will validate the transaction request, then return the beneficiary's transaction + // information using the same unique transaction ID. The TRISANetwork provides both + // a unary RPC for simple, single transactions and a transaction stream for high + // throughput transaction workloads. + rpc Transfer(SecureEnvelope) returns (SecureEnvelope) {} + rpc TransferStream(stream SecureEnvelope) returns (stream SecureEnvelope) {} + + // Address confirmation allows an originator VASP to establish that a beneficiary + // VASP has control of a crypto wallet address, prior to sending transaction + // information with sensitive PII data. + rpc ConfirmAddress(Address) returns (AddressConfirmation) {} + + // The encrypted transaction envelope uses asymmetric (public/private) encryption to + // exchange a symmetric key and signature for the transaction blob. To facilitate + // transaction signatures, VASPs must be able to exchange public signing keys if + // they have not already obtained them from the directory service. + rpc KeyExchange(SigningKey) returns (SigningKey) {} +} + +// The TRISAHealth service is optional but highly recommended for VASP members to +// implement. The Status endpoint allows the TRISA Directory Service to perform health +// checks with VASP's TrISA Node and report the service conditions of the TRISA network. +// Because a down TRISA node will prevent travel rule compliant virtual asset +// transactions, the health service is intended to quickly identify network problems and +// notify members as quickly as possible. +service TRISAHealth { + rpc Status(HealthCheck) returns (ServiceState) {} +} + + +// Encrypted transaction envelope that is the outer layer of the TRISA information +// exchange protocol and facilitates the secure storage of KYC data in a transaction. +// The envelope specifies a unique id to reference the transaction out-of-band (e.g in +// the blockchain layer) and provides the necessary information so that only the +// originator and the beneficiary can decrypt the trnasaction data. +message SecureEnvelope { + // The transaction identifier generated by the sender. Any response + // to a transaction request needs to carry the same identifier. + string id = 1; + + // Encrypted Payload + bytes payload = 2; + + // Encryption key used to encrypt the transaction blob. This key itself + // is encrypted using the public key of the receiver. + bytes encryption_key = 3; + + // The encryption algorithm used to encrypt the transaction blob. + string encryption_algorithm = 4; + + // HMAC signature calculated from encrypted transaction blob. + bytes hmac = 5; + + // The HMAC secret used to calculate the HMAC signature. This secret + // itself is encrypted using the public key of the receiver. + bytes hmac_secret = 6; + + // The algorithm used to calculate the HMAC signature. + string hmac_algorithm = 7; + + // Rejection errors are used inside of a streaming context so that the stream is + // not closed when an exchange-related rejection occurs. In the unary case, errors + // are directly returned rather than as part of the secure envelope. + Error error = 9; +} + +// Payload is the expected message structure that will be parsed from the encrypted +// secure envelope. The Payload should contain the identity and transaction information +// for the information exchange. The internal message types are purposefully generic to +// allow flexibility with the data needs for different exchanges. +message Payload { + // Identity contains any valid identity structure. The recommended format is the + // IVMS101 IdentityPayload which contains the originator and beneficiary identities, + // the originator and beneficiary VASP identities, as well as the transfer path of + // any intermediate VASPs. The identity payload can be bidirectional (containing + // both originator and beneficiary identities) or unidirectional - containing only + // the identity of the sender. In the bidirectional case, the identity may be + // purposefully partial to allow the recipient to fill in the details. In the + // unidirectional case, the identities must be collated after. + google.protobuf.Any identity = 1; + + // Transaction contains network specific information about the exchange or transfer. + google.protobuf.Any transaction = 2; +} + +// TODO: specify the address confirmation protocol. +message Address {} +message AddressConfirmation {} + +// SigningKey provides metadata for decoding a PEM encoded PKIX public key for RSA +// encryption and transaction signing. The SigningKey is a lightweight version of the +// Certificate information stored in the Directory Service. +message SigningKey { + // x.509 metadata information for ease of reference without parsing the key. + int64 version = 1; + bytes signature = 2; + string signature_algorithm = 3; + string public_key_algorithm = 4; + + // Validity information + string not_before = 8; + string not_after = 9; + bool revoked = 10; + + // The PEM encoded public key to PKIX, ASN.1 DER form without the trust chain. + bytes data = 11; +} + +message HealthCheck { + // The number of failed health checks that proceeded the current check. + uint32 attempts = 1; + + // The timestamp of the last health check, successful or otherwise. + string last_checked_at = 2; +} + +message ServiceState { + enum Status { + UNKNOWN = 0; + HEALTHY = 1; + UNHEALTHY = 2; + DANGER = 3; + OFFLINE = 4; + MAINTENANCE = 5; + } + + // Current service status as defined by the recieving system. The system is obliged + // to respond with the closest matching status in a best-effort fashion. Alerts will + // be triggered on service status changes if the system does not respond and the + // previous system state was not unknown. + Status status = 1; + + // Suggest to the directory service when to check the health status again. + string not_before = 2; + string not_after = 3; +} \ No newline at end of file diff --git a/proto/trisa/api/v1beta1/errors.proto b/proto/trisa/api/v1beta1/errors.proto new file mode 100644 index 0000000..4266609 --- /dev/null +++ b/proto/trisa/api/v1beta1/errors.proto @@ -0,0 +1,142 @@ +syntax = "proto3"; + +package trisa.api.v1beta1; +option go_package = "github.com/trisacrypto/trisa/pkg/trisa/api/v1beta1;api"; + +import "google/protobuf/any.proto"; + + +message Error { + enum Code { + option allow_alias = true; + // Errors 0-49 are reserved for service-specific errors + // Default error - something very bad happened. + UNHANDLED = 0; + + // Generic error - could not handle request, retry later. + UNAVAILABLE = 1; + SERVICE_DOWN_TIME = 1; // Alias: Sygna BVRC Rejected Type + BVRC002 = 1; // Alias: Sygna BVRC Rejected Code + + // The service is currently in maintenance mode and cannot respond. + MAINTENANCE = 2; + + // The RPC is not currently implemented by the TRISA node. + UNIMPLEMENTED = 3; + + // Request could not be processed by recipient. + INTERNAL_ERROR = 49; + BVRC999 = 49; // Alias: Sygna BVRC Rejected Code + + // Errors 50-99 are reserved for transaction rejections. + // Default rejection - no specified reason for rejecting the transaction. + REJECTED = 50; + + // VASP does not control the specified wallet address. + UNKNOWN_WALLET_ADDRESS = 51; + + // VASP does not have KYC information for the specified wallet address. + UNKOWN_IDENTITY = 52; + + // Specifically, the Originator account cannot be identified. + UNKNOWN_ORIGINATOR = 53; + + // Specifically, the Beneficiary account cannot be identified. + UNKOWN_BENEFICIARY = 54; + BENEFICIARY_NAME_UNMATCHED = 54; // Alias: Sygna BVRC Rejected Type + BVRC007 = 54; // Alias: Sygna BVRC Rejected Code + + // VASP cannot support the fiat currency or coin described in the transaction. + UNSUPPORTED_CURRENCY = 60; + BVRC001 = 60; // Alias: Sygna BVRC Rejected Code + + // No longer able to receive more transaction inflows + EXCEEDED_TRADING_VOLUME = 61; + BVRC003 = 61; // Alias: Sygna BVRC Rejected Code + + // An internal compliance check has failed or black listing has occurred + COMPLIANCE_CHECK_FAIL = 90; + BVRC004 = 90; // Alias: Sygna BVRC Rejected Code + + // VASP not able to implement travel rule compliance. + NO_COMPLIANCE = 91; + + // VASP unwilling to conduct the transaction because of a risk assessment. + HIGH_RISK = 92; + + // Wallet address or transaction is not available on this network. + OUT_OF_NETWORK = 99; + + // Errors 100-149 are reserved for authentication or cryptography failures. + // Default access denied - no specified reason for forbidding the transaction. + FORBIDDEN = 100; + + // Could not sign transaction because no signing key is available. + NO_SIGNING_KEY = 101; + + // Could not sign transaction because keys have been revoked. + CERTIFICATE_REVOKED = 102; + + // Could not verify certificates with any certificate authority. + UNVERIFIED = 103; + + // A trusted connection could not be established. + UNTRUSTED = 104; + + // An HMAC signature could not be verified + INVALID_SIGNATURE = 105; + + // The transaction bundle cannot be decrypted with the specified key + INVALID_KEY = 106; + + // Could not decode or decrypt private transaction data + ENVELOPE_DECODE_FAIL = 107; + PRIVATE_INFO_DECODE_FAIL = 107; // Alias: Sygna BVRC Rejected Type + BVRC005 = 107; // Alias: Sygna BVRC Rejected Code + + // The algorithm specified by the encryption or signature is not implemented + UNHANDLED_ALGORITHM = 108; + + // Errors 150-199 are reserved for repairing exchange information. + // Generic bad request - usually implies retry when reuqest is fixed. + BAD_REQUEST = 150; + + // Could not parse the identity record; specify the type in extra + UNPARSEABLE_IDENTITY = 151; + PRIVATE_INFO_WRONG_FORMAT = 151; // Alias: Sygna BVRC Rejected Type + BVRC006 = 151; // Alias: Sygna BVRC Rejected Code + + // Could not parse the transaction data record; specify the type in extra + UNPARSEABLE_TRANSACTION = 152; + + // There are missing required fields in the transaction data, a list of these + // fields is specified in extra. + MISSING_FIELDS = 153; + + // The identity record is not complete enough for compliance purposes of the + // receiving VASPs. Required fields or format specified in extra. + INCOMPLETE_IDENTITY = 154; + + // There was an error validating a field in the transaction data (specified in extra) + VALIDATION_ERROR = 155; + } + + // Error codes are standardized in the TRISA network to prevent confusion and to + // allow easy identification of rejections or other problems so that the repair of + // the connection or information exchange can be expedited. + Code code = 1; + + // Human readable message stating the reason for the error, should be loggable and + // actionable. Both standardized and unique/detail messages are acceptable. + string message = 2; + + // If the message that caused the error should be retried with a fix; otherwise the + // rejection is permenant and the request should not be retried. + bool retry = 3; + + // Any additional data or reasons for the rejection, e.g. a parent error, a diff, + // a location for redirect, etc. The payload of the additional data should be + // described by the error code. + google.protobuf.Any details = 4; +} + diff --git a/proto/trisa/gds/api/v1beta1/api.proto b/proto/trisa/gds/api/v1beta1/api.proto new file mode 100644 index 0000000..f7a33d6 --- /dev/null +++ b/proto/trisa/gds/api/v1beta1/api.proto @@ -0,0 +1,199 @@ +syntax = "proto3"; + +package trisads.api.v1alpha1; +option go_package = "github.com/trisacrypto/testnet/pkg/trisads/pb/api/v1alpha1;api"; + +import "ivms101/ivms101.proto"; +import "trisads/models/v1alpha1/models.proto"; +import "trisads/models/v1alpha1/ca.proto"; + + +service TRISACompliance { + // Interactions with the GDS during a TRISA transfer + rpc Lookup(LookupRequest) returns (LookupReply) {} + rpc Search(SearchRequest) returns (SearchReply) {} +} + +service TRISADirectory { + // Registration + rpc Register(RegisterRequest) returns (RegisterReply) {} + rpc VerifyEmail(VerifyEmailRequest) returns (VerifyEmailReply) {} + + // TODO: change to Info/Registration Status + rpc Status(StatusRequest) returns (StatusReply) {} +} + + +message Error { + int32 code = 1; + string message = 2; +} + +// Registration requests are validated that they contain correct information and then +// are sent through the verification process, creating or updating a VASP as needed. +message RegisterRequest { + // The legal entity IVMS 101 data for VASP KYC information exchange. This is the + // IVMS 101 data that should be exchanged in the TRISA P2P protocol as the + // Originator, Intermediate, or Beneficiary VASP fields. A complete and valid + // identity record with country of registration is required. + ivms101.LegalPerson entity = 1; + + // Technical, legal, billing, and administrative contacts for the VASP. + trisads.models.v1alpha1.Contacts contacts = 2; + + // Travel Rule Implementation Endpoint - where other TRISA peers should connect. + // This should be an addr:port combination, e.g. trisa.vaspbot.net:443 + string trisa_endpoint = 3; + + // Common name should be the VASP domain name to issue certificates for, which + // should match the domain in the trisa_endpoint. If this field is omitted, the + // common name is inferred from the trisa_endpoint. + string common_name = 4; + + // Business Information + string website = 5; + trisads.models.v1alpha1.BusinessCategory business_category = 6; + trisads.models.v1alpha1.VASPCategory vasp_category = 7; + string established_on = 8; // Should be a date in YYYY-MM-DD format + + // TRIXO Questionnaire + trisads.models.v1alpha1.TRIXOQuestionnaire trixo = 9; +} + +message RegisterReply { + // If the registration was successful, no error will be returned + Error error = 1; + + // Unique identifiers for the VASP created by the registration. + // Use these identifiers for status lookup requests and any follow-on interactions. + string id = 2; + string registered_directory = 3; + string common_name = 4; + + // The verification status of the VASP entity. + trisads.models.v1alpha1.VerificationState status = 5; + string message = 6; +} + +// Lookup VASP certification information either by their unique ID or by the domain of +// the TRISA implementation endpoint, which should be the common name of the certificate. +// Note that if both id and common name are supplied, ID is prioritized. +message LookupRequest { + // Unique identifier generated by the directory service, most common lookup field. + string id = 1; + + // The URL of the directory that registered the VASP. If ommitted, it is assumed + // that the directory being queried is the registering VASP. + string registered_directory = 2; + + // The common name of the certificate, e.g. the domain name of the TRISA endpoint. + // To use other name fields such as the legal business name, you must use search. + string common_name = 3; +} + +// Summary information is given in return for VASP lookups as lookups are primarily +// intended to facilitate P2P verification and public key exchange. +// NOTE: only verified VASPs are returned using the lookup RPC. +message LookupReply { + // If no error is specified, the lookup was successful + Error error = 1; + + // The uniquely identifying components of the VASP in the directory service + string id = 2; + string registered_directory = 3; + string common_name = 4; + + // The endpoint to connect to for the TRISA P2P protocol (addr:port) + string endpoint = 5; + + // Certificate information if the VASP is available and verified. The identity + // certificate is used to establish mTLS connections, the signing certificate is + // used on a per-transaction basis. + trisads.models.v1alpha1.Certificate identity_certificate = 6; + trisads.models.v1alpha1.Certificate signing_certificate = 7; + + // Other VASP information that faciliates P2P exchanges + string name = 8; + string country = 9; + string verified_on = 10; +} + +// Search requests allow a more flexibly field serach to identify a VASP, these requests +// are primarily used to locate a beneficiary VASP in order to begin the TRISA P2P protocol. +// NOTE: only verified VASPs are returned using the search RPC. +message SearchRequest { + // Case insensitive search fields that use OR to perform the lookup. The name field + // can be the legal, short, or DBA name of the VASP or the common name of + // certificate issued to that VASP (though in this case, it is better to use the + // Lookup RPC). The website must be a parseable URL to lookup the VASP with. + repeated string name = 1; + repeated string website = 2; + + // Search filters to condition the search on. Only VASPs that are in the + // country(ies) or category(ies) specified are returned. + repeated string country = 7; + repeated trisads.models.v1alpha1.BusinessCategory business_category = 8; + repeated trisads.models.v1alpha1.VASPCategory vasp_category = 9; +} + +message SearchReply { + message Result { + // The uniquely identifying components of the VASP in the directory service + string id = 1; + string registered_directory = 2; + string common_name = 3; + + // Address to connect to the remote VASP on to perform a TRISA request + string endpoint = 4; + } + + // If no error is specified, the search was successful, even if no results returned. + Error error = 1; + repeated Result results = 2; +} + +// Check on the status of a VASP including its verification status and the service +// status if the TRISA directory service performs health check monitoring. The same +// parameters as the Lookup RPC are sent, but note that a TRISA directory service may +// refuse to return all or part of the status request. +message StatusRequest { + // Unique identifier generated by the directory service, most common lookup field. + string id = 1; + + // The URL of the directory that registered the VASP. If ommitted, it is assumed + // that the directory being queried is the registering VASP. + string registered_directory = 2; + + // The common name of the certificate, e.g. the domain name of the TRISA endpoint. + // To use other name fields such as the legal business name, you must use search. + string common_name = 3; +} + +message StatusReply { + // If no error is specified, the status request was successful. + Error error = 1; + + // Status information + trisads.models.v1alpha1.VerificationState verification_status = 2; + trisads.models.v1alpha1.ServiceState service_status = 3; + string verified_on = 4; // Should be an RFC 3339 Timestamp + string first_listed = 5; // Should be an RFC 3339 Timestamp + string last_updated = 6; // Should be an RFC 3339 Timestamp +} + +message VerifyEmailRequest { + string id = 1; + string token = 2; +} + +message VerifyEmailReply { + // If no error is specified, the verify email request was successful + Error error = 1; + + // The verification status of the VASP entity. + trisads.models.v1alpha1.VerificationState status = 2; + string message = 3; + + // Used to decrypt the emailed certificates in PKCS 12 format + string pkcs12password = 4; +} \ No newline at end of file diff --git a/proto/trisa/gds/models/v1beta1/ca.proto b/proto/trisa/gds/models/v1beta1/ca.proto new file mode 100644 index 0000000..f0238d9 --- /dev/null +++ b/proto/trisa/gds/models/v1beta1/ca.proto @@ -0,0 +1,99 @@ +syntax="proto3"; + +package trisads.models.v1beta1; +option go_package = "github.com/trisacrypto/directory/pkg/trisads/models/v1beta1;models"; + + +// Certificate requests are maintained separately from the VASP record since they should +// not be replicated. E.g. every directory process is responsible for certificate +// issuance and only public keys and certificate metadata should be exchanged between +// directories. +message CertificateRequest { + // ID only needs to be unique with the requesting directory service. + string id = 1; + + // VASP information for the request + string vasp = 2; + string common_name = 3; + + // Request pipeline status + CertificateRequestState status = 4; + + // Sectigo create single certificate batch metadata + int64 authority_id = 5; + int64 batch_id = 6; + string batch_name = 7; + string batch_status = 8; + int64 order_number = 9; + string creation_date = 10; + string profile = 11; + string reject_reason = 12; + + // Currently there is no choice but to store the PKCS12 password on the server + // because the certificate issuance command is separated in time by human review, + // which means it cannot be ephemerally kept in memory during the certificate + // generation request handoff. Moreover, the value cannot be hashed since it must + // be sent in plaintext via the Sectigo API and used to decrypt the downloaded + // packet in order to retrieve the public key material. To mitigate issues with the + // storage of this data, it is encrypted so that only a directory service with the + // correct secret key (e.g. the directory service process that created the request) + // can read the original value. Because this value should not be replicated it is + // stored in the certificate request which is maintained by independent replicas. + bytes pkcs12password = 13; + bytes pkcs12signature = 14; + + // Logging information timestamps + string created = 15; + string modified = 16; +} + + +message Certificate { + // x.509 metadata information for ease of reference + // note that the serial number as a hex string can be used with the Sectigo API + int64 version = 1; + bytes serial_number = 2; + bytes signature = 3; + string signature_algorithm = 4; + string public_key_algorithm = 5; + + // Issuer and subject information from Sectigo + Name subject = 6; + Name issuer = 7; + + // Validity information + string not_before = 8; + string not_after = 9; + bool revoked = 10; + + // The ASN1 encoded full certificate without the trust chain + bytes data = 11; + + // The complete trust chain including the leaf certificate as a gzip compressed + // PEM encoded file. This field can be deserialized into a trust.Provider. + bytes chain = 12; +} + +// An X.509 distinguished name with the common elements of a DN. +message Name { + string common_name = 1; + string serial_number = 2; + repeated string organization = 3; + repeated string organizational_unit = 4; + repeated string street_address = 5; + repeated string locality = 6; + repeated string province = 7; + repeated string postal_code = 8; + repeated string country = 9; +} + +enum CertificateRequestState { + INITIALIZED = 0; + READY_TO_SUBMIT = 1; + PROCESSING = 2; + DOWNLOADING = 3; + DOWNLOADED = 4; + COMPLETED = 5; + CR_REJECTED = 6; + CR_ERRORED = 7; +} \ No newline at end of file diff --git a/proto/trisa/gds/models/v1beta1/models.proto b/proto/trisa/gds/models/v1beta1/models.proto new file mode 100644 index 0000000..f75c1a6 --- /dev/null +++ b/proto/trisa/gds/models/v1beta1/models.proto @@ -0,0 +1,201 @@ +syntax = "proto3"; + +package trisads.models.v1beta1; +option go_package = "github.com/trisacrypto/directory/pkg/trisads/models/v1beta1;models"; + +import "ivms101/ivms101.proto"; +import "trisads/models/v1beta1/ca.proto"; + +// VASP represents the top-level directory entry for certificate public key exchange. +// The TRISA Directory service allows search and lookup of VASP entries and returns +// TRISA implementation details and certificate key material. VASPs must be registered +// with IVMS 101 identity data for the business entity as well as natural person +// entities for technical, legal, billing, and administrative contacts. +// +// A VASP entry is also the primary point of replication between directories that +// implement the directory replication service. It maintains the version information to +// detect changes with respect to a specific registered directory and faciliates +// anti-entropy gossip protocols. +message VASP { + // A unique identifier generated by the directory service, should be a globally + // unique identifier partitioned specified by the registered directory field. + string id = 1; + + // The url of directory that registered this VASP, e.g. vaspdirectory.net. The + // id of the VASP must must be unique with respect to this field. + string registered_directory = 2; + + // The legal entity IVMS 101 data for VASP KYC information exchange. This is the + // IVMS 101 data that should be exchanged in the TRISA P2P protocol as the + // Originator, Intermediate, or Beneficiary VASP fields. A complete and valid + // identity record with country of registration is required. + ivms101.LegalPerson entity = 3; + + // Technical, legal, billing, and administrative contacts for the VASP. + Contacts contacts = 4; + + // Certificate information and public key material issued to the VASP to facilitate + // mTLS connections between TRISA partners. If the VASP has not been verified then + // the certificate will not be issued. This field is the most recently issued + // certificate but may or may not be revoked. + // In the white paper, this is referred to as the Identity EV-Cert. + Certificate identity_certificate = 5; + + // Signing-key certificates and public key material used to sign transactions. The + // primary use of signing-key certificates is to asymmetrically encrypt and sign + // per-transaction symmetric encryption keys. A VASP can maintain any number of + // signing certificates, which are idnetified by their signature or serial number. + repeated Certificate signing_certificates = 6; + + // Domain name of the TRISA endpoint used as the common name for the certificate. + // This field must be unique per VASP as it identifies the Certificate and is used + // directly in lookups. + string common_name = 7; + + // Travel Rule Implementation Endpoint - where other TRISA peers should connect. + // This should be an addr:port combination, e.g. trisa.vaspbot.net:443 + string trisa_endpoint = 8; + + // Business Information + string website = 9; + BusinessCategory business_category = 10; + VASPCategory vasp_category = 11; + string established_on = 12; // Should be a date in YYYY-MM-DD format + + // TRIXO Questionnaire + TRIXOQuestionnaire trixo = 13; + + // Directory Service Metadata + VerificationState verification_status = 14; + ServiceState service_status = 15; + string verified_on = 16; // Should be an RFC 3339 Timestamp + string first_listed = 17; // Should be an RFC 3339 Timestamp + string last_updated = 18; // Should be an RFC 3339 Timestamp + + // The legal entity signature that is used to verify uniqueness or detect changes. + bytes signature = 19; + + // Version is used for anti-entropy based replication + uint64 version = 20; + + // Temporary: verification token for light weight authentication for verification + // TODO: replace with admin API that uses authentication + string admin_verification_token = 21; +} + +// At least one of the following contact information is required for the VASP to be +// registered in a TRISA directory. Contact information should be kept private in the +// directory service and only used for email communication or verification. +message Contacts { + Contact technical = 1; + Contact administrative = 2; + Contact legal = 3; + Contact billing = 4; +} + +message Contact { + // Name is required to identify and address the contact + string name = 1; + + // An email address is required for all contacts + string email = 2; + + // Phone number is optional, but it is strongly suggested + string phone = 3; + + // Token for email verification + bool verified = 4; + string token = 5; + + // Optional KYC data if required for the directory service contact. + ivms101.NaturalPerson person = 6; +} + +message TRIXOQuestionnaire { + // Should be the name of the country or an ISO-3166-1 code. + string primary_national_jurisdiction = 1; + + // Name of primary financial regulator or supervisory authority. + string primary_regulator = 2; + + // Is the VASP permitted to send and/or receive transfers of virtual assets in the + // jurisdictions in which it operates? + // One of yes, no, partially + string financial_transfers_permitted = 3; + + // Other jurisdictions in which the entity operates. + repeated Jurisdiction other_jurisdictions = 4; + + // Does the VASP have a programme that sets minimum AML, CFT, KYC/CDD and sanctions + // standards per the requirements of the jurisdiction(s) regulatory regimes where + // it is licensed/approved/registered? + // Either yes or no + string has_required_regulatory_program = 5; + + // Does the VASP conduct KYC/CDD before permitting its customers to send/receive + // virtual asset transfers? + bool conducts_customer_kyc = 6; + + // At what threshold does the VASP conduct KYC? + float kyc_threshold = 7; + + // Is the VASP required to comply with the application of the Travel Rule standards + // in the jurisdiction(s) where it is licensed/approved/registered? + bool must_comply_travel_rule = 8; + + // Applicable Travel Regulations the VASP must comply with. + repeated string applicable_regulations = 9; + + // What is the minimum threshold for travel rule compliance? + float compliance_threshold = 10; + + // Is the VASP required by law to safeguard PII? + bool must_safeguard_pii = 11; + + // Does the VASP secure and protect PII, including PII received from other VASPs + // under the Travel Rule? (yes/no) + string safeguards_pii = 12; +} + +message Jurisdiction { + string country = 1; + string regulator_name = 2; + string license_number = 3; +} + +enum BusinessCategory { + UNKNOWN_ENTITY = 0; + PRIVATE_ORGANIZATION = 1; + GOVERNMENT_ENTITY = 2; + BUSINESS_ENTITY = 3; + NON_COMMERCIAL_ENTITY = 4; +} + +enum VASPCategory { + UNKNOWN_VASP = 0; + ATM = 1; + EXCHANGE = 2; + HIGH_RISK_EXCHANGE = 3; +} + +enum VerificationState { + NO_VERIFICATION = 0; + SUBMITTED = 1; + EMAIL_VERIFIED = 2; + PENDING_REVIEW = 3; + REVIEWED = 4; + ISSUING_CERTIFICATE = 5; + VERIFIED = 6; + REJECTED = 7; + APPEALED = 8; + ERRORED = 9; +} + +enum ServiceState { + UNKNOWN = 0; + HEALTHY = 1; + UNHEALTHY = 2; + DANGER = 3; + OFFLINE = 4; + MAINTENANCE = 5; +} \ No newline at end of file