summaryrefslogtreecommitdiff
path: root/design-documents/023-taler-kyc.rst
blob: 604799796657be865433a28682a975191970e839 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
DD 023: Taler KYC
#################

Summary
=======

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
============

Taler needs to run KYC checks in the following circumstances:

* Customer withdraws money over a monthly threshold

  * exchange triggers KYC
  * key: IBAN (encoded as payto:// URI)

* Wallet receives (via refunds) money resulting in a balance over a threshold

  * this is a client-side restriction
  * key: reserve (=KYC account) long term public key per wallet (encoded as payto:// URI)

* Wallet receives money via P2P payments

  * key: reserve (=KYC account) long term public key per wallet (encoded as payto:// URI)

* Merchant receives money (Q: any money, or above a monthly threshold?)

  * key: IBAN (encoded as payto:// URI)



Proposed Solution
=================

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.  If no
KYC was done and if either the amount withdrawn over the last X days exceeds
the threshold or the reserve received received a P2P transfer, then a ``202
Accepted`` is returned which redirects the consumer 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.



Alternatives
============

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
================

(This should be filled in with results from discussions on mailing lists / personal communication.)