summaryrefslogtreecommitdiff
path: root/design-documents
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2021-10-03 13:20:51 +0200
committerChristian Grothoff <christian@grothoff.org>2021-10-03 13:20:51 +0200
commit8f3c14cf93716f3fe2a60b89107403eb96bc2bec (patch)
treeb30059b0e2e8ae131255b877a2db0adcd3202afb /design-documents
parenta99286761f6f4b5870495c94d7c7f365dd7d3bdf (diff)
downloaddocs-8f3c14cf93716f3fe2a60b89107403eb96bc2bec.tar.gz
docs-8f3c14cf93716f3fe2a60b89107403eb96bc2bec.tar.bz2
docs-8f3c14cf93716f3fe2a60b89107403eb96bc2bec.zip
-update KYC DD
Diffstat (limited to 'design-documents')
-rw-r--r--design-documents/023-taler-kyc.rst156
1 files changed, 132 insertions, 24 deletions
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
================