diff options
author | Christian Grothoff <christian@grothoff.org> | 2024-04-19 23:00:29 +0200 |
---|---|---|
committer | Christian Grothoff <christian@grothoff.org> | 2024-04-19 23:00:29 +0200 |
commit | c0c26e784726a9e4ab5f1cf14f99c3d8312c19ea (patch) | |
tree | 2acc99ff9ab2e925f472524cf90845b536194cc5 /design-documents | |
parent | 0fc5dd62d57b722bb1e2b29fc99aa919d6c89324 (diff) | |
download | docs-c0c26e784726a9e4ab5f1cf14f99c3d8312c19ea.tar.gz docs-c0c26e784726a9e4ab5f1cf14f99c3d8312c19ea.tar.bz2 docs-c0c26e784726a9e4ab5f1cf14f99c3d8312c19ea.zip |
update kYC spec
Diffstat (limited to 'design-documents')
-rw-r--r-- | design-documents/023-taler-kyc.rst | 361 |
1 files changed, 293 insertions, 68 deletions
diff --git a/design-documents/023-taler-kyc.rst b/design-documents/023-taler-kyc.rst index 77dbe2bb..e6addbdd 100644 --- a/design-documents/023-taler-kyc.rst +++ b/design-documents/023-taler-kyc.rst @@ -178,8 +178,9 @@ For the user-interactive checks we need a SPA (for KYC) that is given: * instructions to render (with either a form to fill or links to external checks); here the context could provide an array of choices! -* possibly an external check that was set up (if any); for cost-reasons, we should only do one at a time, - and probably should then always redirect the browser to that check. +* possibly an external check that was set up (if any); for cost-reasons, we + should only do one at a time, and probably should then always redirect the + browser to that check. For the staff-interactive checks we need a SPA (for AML): @@ -213,31 +214,69 @@ documents. Terminology ^^^^^^^^^^^ -* **Check**: A check establishes a particular attribute of a user, such as their name based on an ID document and lifeness, mailing address, phone number, taxpayer identity, etc. Checks may be given *context* (such as whether a customer is an individual or a business) to run correctly. Checks can also be AML staff inserting information for plausibilization. Checks result in an *outcome* being decided by an external AML *program*. - -* **Condition**: A condition specifies when KYC is required. Conditions include the *type of operation*, a threshold amount (e.g. above EUR:1000) and possibly a time period (e.g. over the last month). - -* **Configuration**: The configuration determines the *legitimization rules*, and specifies which providers offer which *checks* at what *cost*. - -* **Context**: Context is information provided as input into a *check* and *program* to customize their execution. The context is initially set by the *trigger*, but may evolve as the *account* undergoes *measures*. For each *check* and *program*, the required *context* data must be specified. - -* **Cost**: How much would a client have to pay for a KYC process (if they voluntarily choose to do so for attestation). - -* **Expiration**: KYC legitimizations may be outdated. Expiration rules determine when *checks* have to be performed again. - -* **Legitimization rules**: The legitimization rules determine under which *conditions* which *checks* must be performend and the *expiration* time period for the *checks*. - -* **Logic**: Logic refers to a specific bit of code (realized as an exchange plugin) that enables the interaction with a specific *provider*. Logic typically requires *configuration* for access control (such as an authorization token) and possibly the endpoint of the specific *provider* implementing the respective API. - -* **Measure**: Describes the possible outgoing edges from one state in the state machine (including how to show the current state). Each edge is given some *context* and a *check* to be performed as well as a *program* to decide the *outcome* and the next *measure*. - -* **Outcome**: Describes the account state that an account ends up in due to the result of a *check*. Outcomes can be that an account is frozen (no transactions possible until freeze expires), held (no transactions possible until another *measure* has been taken), or operating normally. Outcomes also include a new set of *legitimization rules* to apply and an expiration time at which point a new *measure* will be automatically taken. Finally, parts of the outcome may be explained to the client (for example, to allow a wallet to stay below hard withdraw thresholds). - -* **Provider**: A provider performs a specific set of *checks* at a certain *cost*. Interaction with a provider is performed by provider-specific *logic*. - -* **Program**: An AML helper *program* is given *context* about the current state of an account and the attribute data from a *check* to compute the *outcome*. For example, a *program* may look at the "PEP" field of a KYC check and decide if the outcome is to put the account into ``normal`` or ``held-for-manual-review`` state. - -* **Type of operation**: The operation type determines which Taler-specific operation has triggered the KYC requirement. We support four types of operation: withdraw (by customer), deposit (by merchant), P2P receive (by wallet) and (high) wallet balance. +* **Check**: A check establishes a particular attribute of a user, such as + their name based on an ID document and lifeness, mailing address, phone + number, taxpayer identity, etc. Checks may be given *context* (such as + whether a customer is an individual or a business) to run correctly. Checks + can also be AML staff inserting information for plausibilization. Checks + result in an *outcome* being decided by an external AML *program*. + +* **Condition**: A condition specifies when KYC is required. Conditions + include the *type of operation*, a threshold amount (e.g. above EUR:1000) + and possibly a time period (e.g. over the last month). + +* **Configuration**: The configuration determines the *legitimization rules*, + and specifies which providers offer which *checks* at what *cost*. + +* **Context**: Context is information provided as input into a *check* and + *program* to customize their execution. The context is initially set by the + *trigger*, but may evolve as the *account* undergoes *measures*. For each + *check* and *program*, the required *context* data must be specified. + +* **Cost**: How much would a client have to pay for a KYC process (if they + voluntarily choose to do so for attestation). + +* **Expiration**: KYC legitimizations may be outdated. Expiration rules + determine when *checks* have to be performed again. + +* **Legitimization rules**: The legitimization rules determine under which + *conditions* which *checks* must be performend and the *expiration* time + period for the *checks*. + +* **Logic**: Logic refers to a specific bit of code (realized as an exchange + plugin) that enables the interaction with a specific *provider*. Logic + typically requires *configuration* for access control (such as an + authorization token) and possibly the endpoint of the specific *provider* + implementing the respective API. + +* **Measure**: Describes the possible outgoing edges from one state in the + state machine (including how to show the current state). Each edge is given + some *context* and a *check* to be performed as well as a *program* to + decide the *outcome* and the next *measure*. + +* **Outcome**: Describes the account state that an account ends up in due to + the result of a *check*. Outcomes can be that an account is frozen (no + transactions possible until freeze expires), held (no transactions possible + until another *measure* has been taken), or operating normally. Outcomes + also include a new set of *legitimization rules* to apply and an expiration + time at which point a new *measure* will be automatically taken. Finally, + parts of the outcome may be explained to the client (for example, to allow a + wallet to stay below hard withdraw thresholds). + +* **Provider**: A provider performs a specific set of *checks* at a certain + *cost*. Interaction with a provider is performed by provider-specific + *logic*. + +* **Program**: An AML helper *program* is given *context* about the current + state of an account and the attribute data from a *check* to compute the + *outcome*. For example, a *program* may look at the "PEP" field of a KYC + check and decide if the outcome is to put the account into ``normal`` or + ``held-for-manual-review`` state. + +* **Type of operation**: The operation type determines which Taler-specific + operation has triggered the KYC requirement. We support four types of + operation: withdraw (by customer), deposit (by merchant), P2P receive (by + wallet) and (high) wallet balance. 451 Response @@ -273,7 +312,7 @@ body. } -New Endpoints +New endpoints ^^^^^^^^^^^^^ .. http:get:: /kyc-check/$REQUIREMENT_ROW @@ -859,8 +898,11 @@ New Endpoints Note that this is merely a simple authentication mechanism, the details of the request are not protected by the signature. - :query start_date=TIMESTAMP: *Optional*. Specifies the date when to start looking (inclusive). If not given, the start time of the exchange operation is used. - :query end_date=TIMESTAMP: *Optional*. Specifies the date when to stop looking (exclusive). If not given, the current date is used. + :query start_date=TIMESTAMP: *Optional*. Specifies the date when to + start looking (inclusive). If not given, the start time of the + exchange operation is used. + :query end_date=TIMESTAMP: *Optional*. Specifies the date when to + stop looking (exclusive). If not given, the current date is used. **Response**: @@ -869,7 +911,206 @@ New Endpoints interface EventCounter { // Number of events of the specified type in // the given range. - cnt: Integer; + counter: Integer; + } + +.. http:get:: /aml/$OFFICER_PUB/decisions/$STATE + + Obtain list of AML decisions (filtered by $STATE). ``$STATE`` must be + either ``normal``, ``pending`` or ``frozen``. + + *Taler-AML-Officer-Signature*: The client must provide Base-32 encoded EdDSA + signature with ``$OFFICER_PRIV``, affirming the desire to obtain AML data. + Note that this is merely a simple authentication mechanism, the details of + the request are not protected by the signature. + + :query limit: *Optional*. takes value of the form ``N (-N)``, so that at + most ``N`` values strictly older (younger) than ``start`` are returned. + Defaults to ``-20`` to return the last 20 entries (before ``start``). + :query offset: *Optional*. Row number threshold, see ``delta`` for its + interpretation. Defaults to ``INT64_MAX``, namely the biggest row id + possible in the database. + + **Response** + + :http:statuscode:`200 OK`: + The responds will be an `AmlRecords` message. + :http:statuscode:`204 No content`: + There are no matching AML records. + :http:statuscode:`403 Forbidden`: + The signature is invalid. + :http:statuscode:`404 Not found`: + The designated AML account is not known. + :http:statuscode:`409 Conflict`: + The designated AML account is not enabled. + + **Details:** + + .. ts:def:: AmlRecords + + interface AmlRecords { + + // Array of AML records matching the query. + records: AmlRecord[]; + } + + .. ts:def:: AmlRecord + + interface AmlRecord { + + // Which payto-address is this record about. + // Identifies a GNU Taler wallet or an affected bank account. + h_payto: PaytoHash; + + // What is the current AML state. + current_state: Integer; + + // Monthly transaction threshold before a review will be triggered + threshold: Amount; + + // Row ID of the record. Used to filter by offset. + rowid: Integer; + + } + + +.. http:get:: /aml/$OFFICER_PUB/decision/$H_PAYTO + + Obtain deails about an AML decision. + + *Taler-AML-Officer-Signature*: The client must provide a Base-32 + encoded EdDSA signature with ``$OFFICER_PRIV``, affirming the + desire to obtain AML data. Note that this is merely a simple + authentication mechanism, the details of the request are not + protected by the signature. + + :query history: *Optional*. If set to yes, we return all historic + decisions for the account, and not only the last one. + + **Response** + + :http:statuscode:`200 OK`: + The responds will be an `AmlDecisionDetails` message. + :http:statuscode:`204 No content`: + There are no matching AML records for the given payto://-URI. + :http:statuscode:`403 Forbidden`: + The signature is invalid. + :http:statuscode:`404 Not found`: + The designated AML account is not known. + :http:statuscode:`409 Conflict`: + The designated AML account is not enabled. + + **Details:** + + .. ts:def:: AmlDecisionDetails + + interface AmlDecisionDetails { + + // Array of AML decisions made for this account. Possibly + // contains only the most recent decision if "history" was + // not set to 'true'. + aml_history: AmlDecisionDetail[]; + + // Array of KYC attributes and outcomes obtained for this + // account. + kyc_attributes: KycDetail[]; + } + + .. ts:def:: AmlDecisionDetail + + interface AmlDecisionDetail { + + // What was the justification given? + justification: string; + + // When does the outcome expire? + expiration_time: Timestamp; + + // KYC rules to apply. Note that this + // overrides *all* of the default rules + // until the ``expiration_time`` and specifies + // the successor measure to apply after the + // expiration time. + new_rules: LegitimizationRules; + + // When was this decision made? + decision_time: Timestamp; + + // Who made the decision? + decider_pub: AmlOfficerPublicKeyP; + + } + + .. ts:def:: KycDetail + + interface KycDetail { + + // Name of the configuration section that specifies the provider + // which was used to collect the KYC details + provider_section: string; + + // The collected KYC data. NULL if the attribute data could not + // be decrypted (internal error of the exchange, likely the + // attribute key was changed). + attributes?: Object; + + // Time when the KYC data was collected + collection_time: Timestamp; + + // Outcome of the AML program. + outcome: AmlProgramOutcome; + + } + + + .. http:post:: /aml/$OFFICER_PUB/decision + + Make an AML decision. Triggers the respective action and + records the justification. + + **Request:** + + The request must be an `AmlDecision` message. + + **Response** + + :http:statuscode:`204 No content`: + The AML decision has been executed and recorded successfully. + :http:statuscode:`403 Forbidden`: + The signature is invalid. + :http:statuscode:`404 Not found`: + The address the decision was made upon is unknown to the exchange or + the designated AML account is not known. + :http:statuscode:`409 Conflict`: + The designated AML account is not enabled or a more recent + decision was already submitted. + + **Details:** + + .. ts:def:: AmlDecision + + interface AmlDecision { + + // Human-readable justification for the decision. + justification: string; + + // Which payto-address is the decision about? + // Identifies a GNU Taler wallet or an affected bank account. + h_payto: PaytoHash; + + // When does the outcome expire? + expiration_time: Timestamp; + + // What are the new rules? + new_rules: LegitimizationRules; + + // When was the decision made? + decision_time: Timestamp; + + // Signature by the AML officer over a `TALER_AmlDecisionPS`. + // Must have purpose ``TALER_SIGNATURE_MASTER_AML_KEY``. + officer_sig: EddsaSignature; + } @@ -1125,14 +1366,10 @@ AML programs are helper programs that can: // JSON array with the results of historic // AML desisions about the account. - // FIXME: review AmlDecisionDetail spec! - // (need to enable new outcomes!) aml_history: AmlDecisionDetail[]; // JSON array with the results of historic // KYC data about the account. - // FIXME: review KycDetail spec! - // (need to include AmlProgramOutcome!) kyc_history: KycDetail[]; } @@ -1167,20 +1404,12 @@ AML programs are helper programs that can: // When does the outcome expire? expiration_time: Timestamp; - // Name of the measure to apply the outcome expires. - // If not set, we revert to the default set - // of rules (and the default account state). - successor_measure?: string; - - // Array of KYC rules to apply. Note that this - // array overrides *all* of the default rules. - // Thus, if the array does not have an entry for - // a particular operation, there would be - // no thresholds for that operation! - rules: KycRule[]; - - // Custom measures that KYC rules may refer to. - custom_measures?: { "name" : MeasureInformation }; + // KYC rules to apply. Note that this + // overrides *all* of the default rules + // until the ``expiration_time`` and specifies + // the successor measure to apply after the + // expiration time. + new_rules: LegitimizationRules; } @@ -1596,25 +1825,21 @@ exteral KYC check and redirecting there. FORM is about displaying a particular (HTML) form to the user and POSTing the entered information directly with the exchange. Here we describe the forms that must be supported: -* CHOICE: Asks the client a multiple-choice question. - The context must include "choices: string[]" with - a list of choices to show. Used, for example, to - ask a client if they are an individual or a business. - The resulting HTML FORM field name must be - "choice" and it must be mapped to strings from the - choices list. -* UPLOAD: Asks the client to upload a single file. - The context may include "extensions: string[]" with - a list of allowed file extensions the client's file - must end with (e.g. "png", "pdf", "gif"). In the - absence of this context, any file may be uploaded. - The context may also include "size_limit: Integer" with - the maximum file size in bytes that can be uploaded. - The resulting HTML FORM must have two fields, - "filename" and "filedata". "filename" must be - set to the basename of the original file (to the - extend that it is available), and "filedata" - to the base64-encoding of the uploaded data. +* **CHOICE**: Asks the client a multiple-choice question. The context must + include "choices: string[]" with a list of choices to show. Used, for + example, to ask a client if they are an individual or a business. The + resulting HTML FORM field name must be "choice" and it must be mapped to + strings from the choices list. + +* **UPLOAD**: Asks the client to upload a single file. The context may include + "extensions: string[]" with a list of allowed file extensions the client's + file must end with (e.g. "png", "pdf", "gif"). In the absence of this + context, any file may be uploaded. The context may also include + "size_limit: Integer" with the maximum file size in bytes that can be + uploaded. The resulting HTML FORM must have two fields, "filename" and + "filedata". "filename" must be set to the basename of the original file (to + the extend that it is available), and "filedata" to the base64-encoding of + the uploaded data. As with other SPA checks, the KYC form should also show the description of the check. |