From 8f3c14cf93716f3fe2a60b89107403eb96bc2bec Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Sun, 3 Oct 2021 13:20:51 +0200 Subject: -update KYC DD --- design-documents/023-taler-kyc.rst | 156 +++++++++++++++++++++++++++++++------ 1 file changed, 132 insertions(+), 24 deletions(-) (limited to 'design-documents') diff --git a/design-documents/023-taler-kyc.rst b/design-documents/023-taler-kyc.rst index aba65a9a..12a4cf00 100644 --- a/design-documents/023-taler-kyc.rst +++ b/design-documents/023-taler-kyc.rst @@ -4,12 +4,15 @@ DD 023: Taler KYC Summary ======= -This document discusses the KYC processes supported by Taler. +This document discusses the Know-your-customer (KYC) processes supported by Taler. Motivation ========== +To legally operate, Taler has to comply with KYC regulation that requires +banks to identify parties involved in transactions at certain points. + Requirements ============ @@ -21,54 +24,159 @@ Taler needs to run KYC checks in the following circumstances: * exchange triggers KYC * key: IBAN -* Wallet receives (via refunds) money over a monthly threshold +* Wallet receives (via refunds) money resulting in a balance over a threshold * this is a client-side restriction - * key: reserve public key (generated, long-term) + * key: reserve (=KYC account) public key (generated, long-term) * Wallet receives money via P2P payments * key: reserve (=KYC account) public key -* Merchant receives money above a monthly threshold +* Merchant receives money (Q: any money, or above a monthly threshold?) * key: IBAN + Proposed Solution ================= -The new taler-kyc-ledger component keeps track of a mapping between an -identifier (as a payto URI?) and a KYC status (yes-merchant, yes-customer, no, -progress (with resume link)). Different identifiers might be mapped by the -bank's KYC provider to the same legal user entity. - -Identifier: - -* IBAN -* reserve / account - -What info do we look at to determine if threshold is crossed / being crossed? +Exchange modifications +^^^^^^^^^^^^^^^^^^^^^^ + +We introduce a new ``wire_targets`` table into the exchange database. This +table is referenced as the source or destination of payments (regular deposits +and also P2P payments). A positive side-effect is that we reduce duplication +in the ``reserves_in``, ``wire_out`` and ``deposits`` tables as they can +reference this table. In this table, we additionally store information +related to the KYC status of the underlying payto://-URI. + +A new ``/kyc/`` endpoint is based on the ``wire_targets`` serial +number. Access is ``authenticated`` by also passing the hash of the +payto://-URI (weak authentication is acceptable, as the KYC status or the +ability to initiate a KYC process are not very sensitive). Given this pair, +the ``/kyc/`` endpoint returns either the (positive) KYC status or redirects +the client (302) to the current stage of the KYC process. The redirection is +offered using an HTTP-redirect for Web-based clients and a JSON body with +information for triggering App-based KYC (via intents or opening some new type +of KYC URI). + +A new ``/management/kyc/`` endpoint is introduced that allows exchange +operators to reset the KYC status (using hash of payto:// as the key) of +certain account holders. Batch operations should likely be supported (where an +array of hashes is provided). The handler should return the number of +accounts that were actually modified. The idea is that the bank would use this +to update its KYC records given an updated list of embargoed entities. +This will also require a new ``taler-exchange-offline`` subcommand. + +When withdrawing, the exchange checks if the KYC status is acceptable, and if +not if the amount withdrawn over the last X days exceeds the threshold. If +the check fails, the consumer is redirected to the new ``/kyc/`` handler. + +When depositing, the exchange checks the KYC status and if negative, returns an +additional information field that tells the merchant the ``wire_target_serial`` +number needed to begin the KYC process (this is independent of the amount) +at the new ``/kyc/`` handler. + +When tracking deposits, the exchange also adds the ``wire_target_serial`` to +the reply if the KYC status is negative. + +The aggregator is modified to only create the ``wire_out`` record, but not +the ``prewire`` record. + +A new ``taler-exchange-kyc`` process checks ``wire_out`` records for which the +``wire_target`` has the KYC status set to positive, and creates ``prewire`` +records (and sets the ``wire_out`` to ``done``. + +We may want to consider directly deleting prewire records instead of setting +them to ``finished`` in ``taler-exchange-transfer``. + + +Merchant modifications +^^^^^^^^^^^^^^^^^^^^^^ + +We introduce new ``kyc_status``, ``kyc_timestamp`` and ``kyc_serial`` fields +into a new table with primary keys ``exchange_url`` and ``account``. This +status is updated whenever a deposit is created or tracked, or whenever the +mechant backend receives a ``/kyc/`` response from the exchange. Initially, +``kyc_serial`` is zero, indicating that the merchant has not yet made any +deposits and thus does not have an account at the exchange. + +A new private endpoint ``/kyc/`` is introduced which allows frontends to +request the ``/kyc/`` status of any configured account (including with long +polling). If the KYC status is negative or the ``kyc_timestamp`` not recent +(say older than one month), the merchant backend will re-check the KYC status +at the exchange (and update its cached status). The endpoint then returns +either that the KYC is OK, or information (same as from the exchange endpoint) +to begin the KYC process. + +The merchant backend uses the new field to remember that a KYC is pending +(after ``/deposit``, or tracing deposits) and the SPA then shows a +notification whenever the staff is logged in to the system. The notification +can be hidden for the current day (remembered in local storage). + +The notification links to a (new) KYC status page. When opened, the KYC status +page first re-checks the KYC status with the exchange. If the KYC is still +unfinished, that page contains another link to begin/resume the KYC process, +otherwise it shows that the KYC process is done. If the KYC is unfinished, the +SPA should use long-polling on the KYC status on this page to ensure it is +always up-to-date, and change to ``KYC satisfied`` should the long-poller +return with positive news. + + +Bank requirements +^^^^^^^^^^^^^^^^^ + +The exchange primarily requires two endpoints from the bank, one to initiate a +KYC process, and a second one to check if a KYC process has successfully +completed. The latter must also be accessible to the auditor. Here, the +exchange (or auditor) would preferably pass either the (1) hash of the +payto://-URI, (2) the payto://-URI itself, or (3) its ``kyc_serial`` into the +bank's KYC APIs. (1) is likely best as it contains the least sensitive +information in the request and still allows the auditor to make a semantically +meaningful request to the bank's KYC API; (2) may allow the bank to extract +the IBAN, which could be helpful in certain cases but might limit the +introduction of new URI schema and may leak information; (3) is most compact +in terms of what the bank would have to persist with its KYC data, but would +theoretically allow the exchange to manipulate indices to not pay out certain +customers despite them having done KYC without easy detection by the auditor. + +If possible, the endpoint to check if a KYC process has finished would +support long-polling. + +If possible, the process that allows the user to perform the KYC would +allow us to trigger the exchange's ``/kyc/`` endpoint at the end, to +allow the exchange to immediately learn about the completed process. -[ ... ] - -FIXME: Who keeps track of the threshold? -* since the kyc-ledger might be run by the bank and - not the exchange, the thresholds could/should be kept by - the exchange - -* kyc-ledger vs kyc-provider Alternatives ============ -None unless we want regulatory compliance? +We could have some (new?) component periodically re-check the KYC status of +all targets for which the status is currently negative (and for which we have +pending outgoing transactions). However, this may just put undue burden on the +bank's KYC API. + +The bank's KYC API could return a unique identifier to the exchange whenever +it initiates a KYC process, and the exchange could store that ID. However, +this may create issues if multiple KYC processes are initiated for the same +entity (and this is likely not detectable by the bank at that time). Also, +this information would again not be reasonably verifiable by the auditor. Drawbacks ========= +If the bank fails to trigger the ``/kyc/`` handler of the exchange after +completion of the KYC process, the exchange will not notice the status change +until the merchant backend makes the next inquiry (which would usually have to +be triggered manually by the merchant). + +The solution may require changes to the bank's existing KYC implementation to +store the KYC status under the (hash of the) payto://-URI. + Discussion / Q&A ================ -- cgit v1.2.3