taler-docs

Documentation for GNU Taler components, APIs and protocols
Log | Files | Refs | README | LICENSE

023-taler-kyc.rst (73207B)


      1 DD 23: Taler KYC
      2 ################
      3 
      4 Summary
      5 =======
      6 
      7 This document discusses the Know-your-customer (KYC) and Anti-Money Laundering
      8 (AML) processes supported by Taler.
      9 
     10 
     11 Motivation
     12 ==========
     13 
     14 To legally operate, Taler has to comply with KYC/AML regulation that requires
     15 banks to identify parties involved in transactions at certain points.
     16 
     17 
     18 Requirements
     19 ============
     20 
     21 Taler needs to take *measures* based on the following primary *triggers*:
     22 
     23 * Customer withdraws money over a monthly threshold
     24 
     25   * exchange triggers KYC
     26   * key: IBAN (encoded as payto:// URI)
     27 
     28 * Wallet receives (via refunds) money resulting in a balance over a threshold
     29 
     30   * this is a client-side restriction
     31   * key: reserve (=KYC account) long term public key per wallet (encoded as payto:// URI)
     32 
     33 * Wallet receives money via P2P payments
     34 
     35   * there are two sub-cases: PUSH and PULL payments
     36   * key: reserve (=KYC account) long term public key per wallet (encoded as payto:// URI)
     37 
     38 * Merchant receives money (Q: any money, or above a monthly threshold?)
     39 
     40   * key: IBAN (encoded as payto:// URI)
     41 
     42 * Reserve is "opened" for invoicing.
     43 
     44   * key: reserve (=KYC account) long term public key per wallet (encoded as payto:// URI)
     45 
     46 * Import of new sanctions lists and triggering of measures against matches of existing
     47   customer records against the list
     48 
     49 For the different operation types, there can be both soft and hard
     50 limits. Soft limits are those that the customer may raise by providing data
     51 and passing KYC checks.  Hard limits cannot be lifted, for example because an
     52 exchange forbids crossing those limits in its terms of service for all
     53 customers.
     54 
     55 
     56 Process requirements
     57 ^^^^^^^^^^^^^^^^^^^^
     58 
     59 The key consideration here is *plausibilization*: staff needs to
     60 check that the client-provided information is plausible. As this
     61 is highly case-dependent, this cannot be automated.
     62 
     63 For the different *measures*, there are various different possible KYC/AML
     64 *checks* that could happen:
     65 
     66 * In-person validation by AML staff
     67 * Various forms to be filled by AML staff
     68 * Validation involving local authorities and post-office
     69 * Online validation, sometimes with multiple options (like KYC for multiple people):
     70 
     71   * Forms to be supplied by user (different types of ID)
     72   * Interactive video
     73   * Documents to be supplied (business register)
     74   * Address validation (e-mail or phone or postal)
     75 
     76 Additionally, the process is dynamic and conditional upon various decisions:
     77 
     78 * Individual vs. business
     79 * PEP or non-PEP
     80 * Hit on sanctions list
     81 * Type of business (trust, foundation, listed on stock market, etc.)
     82 * Need for plausibilization (via documents by user or staff research)
     83 * Periodic updates (of customer data, of sanction lists) and re-assessment
     84 
     85 There are also various *outcomes*:
     86 
     87 * normal operation (with expiration date)
     88 * normal operation but with AML staff investigating (new measure)
     89 * held, requesting customer documentation (new measure)
     90 * held, AML staff reviewing evidence for plausibilization (new measure)
     91 * automatically frozen until certain day (due to sanctions)
     92 * institutionally frozen until certain day (due to order by state authority)
     93 * operation is categorically not allowed (at least above certain limits)
     94 
     95 Outcomes may also be (partially) public, that is exposed to the client. For
     96 example, we may want to tell a wallet that it has hit a hard withdraw limit,
     97 but might succeed at withdrawing a smaller amount.
     98 
     99 The outcome of a *check* can set new rules or trigger another *measure* (the
    100 latter is conditional on reaching the expiration time of the outcome).
    101 
    102 As a result, we largely end up in a large state machine where the AML staff has
    103 serious flexibiltiy while the user needs guidance as to the possible next moves
    104 and/or to the current state of their account (where some information must not be
    105 disclosed).
    106 
    107 
    108 Documentation requirements
    109 ^^^^^^^^^^^^^^^^^^^^^^^^^^
    110 
    111 For each account we must:
    112 
    113 * define risk-profile (902.4, 905.1)
    114 * document the specific setup, likely not just the INI file
    115 * should have some key Anti-Money-Laundering Act (AMLA)
    116   file attributes, such as:
    117 
    118   * File opened, file closed (keep data for X years afterwards!)
    119   * low-risk or high-risk business relationship
    120   * PEP status
    121   * business domain
    122   * authority notification dates (possibly multiple) with
    123     voluntary or mandatory notification classification
    124 
    125 Finally, we need to produce statistics:
    126 
    127 * There must be a page with an overview of AMLA files with opening
    128   and closing dates and an easy way to determine for any day the
    129   number of open AMLA files
    130 * Technically, we also need a list of at-risk transactions and of
    131   frozen transactions, but given that we can really only freeze
    132   on an account-basis, I think there is nothing to do here
    133 * number of incidents reported (voluntarily, required)
    134 * number of business relationships at any point in time
    135 * number of risky business relationships (PEP, etc.)
    136 * number of frozen transactions (authority vs. sanction) with start-date and end-date
    137 * start-data and end-date of relationships (data retained for X years after end of relationship)
    138 
    139 For this high-level monitoring, we need certain designated critical events to
    140 be tracked in the system statistics:
    141 
    142 * account opened
    143 * set to high risk
    144 * set to low risk
    145 * suspicious activity report filed with authority
    146 * account frozen
    147 * account unfrozen
    148 * account closed
    149 * sanction list import / update
    150 
    151 
    152 TODO: Sanction lists
    153 ^^^^^^^^^^^^^^^^^^^^
    154 
    155 We need to be able to import new sanction lists (whenever they are published)
    156 and then check existing AMLA files against those lists.  Additionally, newly
    157 created AMLA files must be checked against the current list and some "measure"
    158 applied in case of a match.
    159 
    160 This will primarily require us to define an endpoint to upload a sanction list
    161 and to define a new table to track the list of sanctioned entities.  As it is
    162 expected that sanction lists will not permit fully automated determinations in
    163 all cases, an external "sanction check" program should be configured which
    164 compares records against the current list and determines the correct measure,
    165 such as no change, further manual review by AML staff, or even automatic
    166 freeze (and report) depending on how well the records match.
    167 
    168 Basically, the "sanction check" program takes the sanction list and an
    169 attribute set to compute the same kind of `AmlOutcome` that an AML program
    170 outputs given a context and an attribute set.
    171 
    172 
    173 Security requirements
    174 ^^^^^^^^^^^^^^^^^^^^^
    175 
    176 IBANs are predictable. We (probably) do not want random people to be able to
    177 initate KYC processes for other parties. Similarly, the attestation API
    178 requires us to somehow *authenticate* the user to ensure we only give out
    179 attestation data to the data subject themselves. For P2P payments and
    180 withdrawals, we have the reserve public key that is only known to the data
    181 subject and thus can be used to authenticate the client via a signature. Only
    182 pure deposits (by merchants or directly from a wallet) are a problem as the
    183 only thing we know about the receiver is the IBAN at that time, and literally
    184 any user could just deposit money into some bank account, so knowledge of the
    185 IBAN is insufficient to determine that we actually are communicating with the
    186 owner of the bank account.
    187 
    188 
    189 Further considerations
    190 ^^^^^^^^^^^^^^^^^^^^^^
    191 
    192 On top of all of this, we need to plan some *diagnostics* to determine when
    193 components fail (such as scripts or external services providing malformed
    194 results).
    195 
    196 Optionally, in the future, the solution should support fees to be paid by the
    197 user for *voluntary* KYC processes related to attestation (#7365).
    198 
    199 
    200 Proposed Solution
    201 =================
    202 
    203 The main state of an account is represented by a set of `KYC rules <KycRule>` (the
    204 `LegitimizationRuleSet`) which specify the current *rules* to apply to
    205 transactions involving the account. Rules can *exposed* to the account owner,
    206 or can be secret.  Each *rule* specifies certain *conditions* which, if met,
    207 *trigger* a set of *measures*.  After a *rule* was *triggered* and
    208 before the *outcome* of a respective *measure* has been produced (say
    209 because the user did not yet enter their data or the AML officer is still
    210 reviewing the case), the existing rules remain in force. Rules have a display
    211 priority, and if a second rule with a higher display priority is also
    212 triggered, the *measures* of the higher-priority rule become the active
    213 *measures*.  Except for the default rule set, every legitimization rule set
    214 also has an *expiration* time after which a successor *measure* (or the
    215 default rule set) is automatically triggered.
    216 
    217 For any possible *measures*, we define:
    218 
    219 * Contextual input data to be provided (with dynamic inputs,
    220   e.g. amount set dynamically based on the *trigger* could be
    221   in the context)
    222 * A *check* to be performed (checks can be user-interactive (LINK, FORM)
    223   or staff-interactive (INFO))
    224 * A fallback *measure* to take on failure of a user-interactive check
    225   (if the check fails, we cannot run the AML *program* as required inputs
    226   might be missing!)
    227 * An (AML) *program* that uses *attribtes* from the *check* as well as
    228   *context* data to determine an *outcome* represented as the
    229   `AmlOutcome`.
    230 
    231 "verboten" is the name of a special *measure*, which means that crossing the
    232 respective transaction threshold is categorically not allowed (for this
    233 account).  "verboten" with a threshold of zero can be used to freeze funds.
    234 
    235 Possible *outcomes* of a measure include:
    236 
    237 * The next operational state (normal, AML investigation) of the account
    238   (basically, whether to add it to the work list of AML staff).
    239 * A new set of *rules* in the form of a `LegitimizationRuleSet` that
    240   determines custom rules to apply to transactions involving the account;
    241   such rules may be used to block certain transactions by using the
    242   "verboten" measure.  The `LegitimizationRuleSet` also must specify
    243   an *expiration* time by which we fall back to a successor measure
    244   *or* to the default rules.
    245 * A (largely) free-form set of `AccountProperties` that AML staff can
    246   use to tag accounts with. Some default properties are defined, but
    247   the exchange does not do anything with these and AML SPAs are free to
    248   use any properties they like.  Account properties are only exposed
    249   to AML staff and never to the customer.
    250 * A set of *events* that are to be added to the timeline of the
    251   operator for statistical purposes.
    252 
    253 For the user-interactive *checks* we need a KYC SPA that is given:
    254 
    255 * instructions to render (with either a form to fill or links to external checks);
    256   here the context could provide an array of choices!
    257 * possibly an external check that was set up (if any); for cost-reasons, we
    258   should only do one at a time, and probably should then always redirect the
    259   browser to that check.
    260 
    261 For the staff-interactive *checks* we need an AML SPA:
    262 
    263 * to file forms and upload documentation (without state transition)
    264 * to decide on next measure (providing context); here, the exchange needs
    265   to expose the list of available *measures* and required *context* for each
    266 
    267 We need some customer-driven interactivity in KYB/KYC process, for example the
    268 user may need to be given choices (address vs. phone, individual vs. business,
    269 order in which to provide KYC data of beneficiaries). As a result, the
    270 exchange needs to serve some SPA for *measures* where the user is shown the
    271 next step(s) or choices (which person to collect KYC data on, whether to run
    272 challenger on phone number of physical address, etc.).  The SPA should also
    273 potentially contain a form to allow the customer to directly upload documents
    274 to us (like business registration) instead of to some KYC provider. This is
    275 because KYC providers may not be flexible enough.  The SPA should also allow
    276 the customer to perform KYC checks voluntarily.
    277 
    278 Similarly, the AML staff will need to be able to trigger rather complex
    279 KYB/KYC processes, like "need KYC on X and Y and Z" or "phone number or
    280 mailing address" or "please upload form A/T/S".  Here in particular it
    281 should be possible to request not only filled forms, but arbitrary
    282 documents.
    283 
    284 
    285 Terminology
    286 ^^^^^^^^^^^
    287 
    288 * **Attributes**: Attributes are used to represent KYC data obtained about
    289   an account holder. Attributes include passport images, address data,
    290   business registration documents, and indeed arbitrary forms filed by
    291   AML staff or the customer themselves.  Attribute data is considered
    292   sensitive private information and is thus stored encrypted within the
    293   exchange database.
    294 
    295 * **Check**: A check establishes a particular attribute of a user, such as
    296   their name based on an ID document and lifeness, mailing address, phone
    297   number, taxpayer identity, etc.  Checks may be given *context* (such as
    298   whether a customer is an individual or a business) to run correctly. Checks
    299   can also be AML staff inserting information for plausibilization.  Checks
    300   result in *attributes* about the account's owner which are given to an
    301   external AML *program* together with the *context* to determine an *outcome*.
    302   KYC checks are always specified with a fallback *measure* to be taken if
    303   the check fails.
    304 
    305 * **Condition**: A condition specifies when KYC is required. Conditions
    306   include the *type of operation*, a threshold amount (e.g. above EUR:1000)
    307   and possibly a time period (e.g. over the last month).
    308 
    309 * **Configuration**: The configuration determines the *legitimization rules*,
    310   and specifies which providers offer which *checks*.
    311 
    312 * **Context**: Context is information provided as input into a *check* and
    313   *program* to customize their execution. The context is initially set by the
    314   *measure* (possibly including data from the *trigger*).  Naturally, the
    315   *program* may use its `AmlProgramInput` which includes *context* and
    316   *attribute* data to compute an update *context* for the next set of
    317   *measures* that it specifies in the `LegitimizationRuleSet` as part
    318   of the `AmlOutcome`.  Thus, *context* is something that typically
    319   evolves as the *account* undergoes *measures*.  Context is lost if
    320   an account transitions to default *legitimization rules* due to
    321   *expiration*.
    322 
    323 * **Display priority**: Every rule has a *display priority*. If a second
    324   *rule* is *triggered* before the *outcome* of a *rule* could be determined,
    325   the *rule* with the larger *display priority* becomes the requirement that
    326   the account owner has to satisfy (and that thus will be displayed by the
    327   KYC SPA).
    328 
    329 * **Expiration**: Except for the default rules, any set of KYC rules is
    330   subject to *expiration*. This can be because *attributes* become outdated or
    331   because sanctions have a time limit. The expiration time thus determines
    332   when a new *measure* is triggered in the absence of a transaction crossing
    333   thresholds in the current set of *legtimization rules*.
    334 
    335 * **Legitimization rules**: The *legitimization rules* determine under which
    336   *conditions* which *measures* will be taken. A `LegitimizationRuleSet`
    337   always also includes an *expiration* time period for (custom, non-default)
    338   *legitimization rules* after which a fallback measure* will automatically
    339   apply.  Legitimization rules may be *exposed* to the client (for example,
    340   to allow a wallet to stay below hard withdraw thresholds) or could be secret.
    341 
    342 * **Logic**: Logic refers to a specific bit of code (realized as an exchange
    343   plugin) that enables the interaction with a specific *provider*.  Logic
    344   typically requires *configuration* for access control (such as an
    345   authorization token) and possibly the endpoint of the specific *provider*
    346   implementing the respective API.
    347 
    348 * **Measure**: Describes the possible outgoing edges from one state in the
    349   state machine (including how to show the current state). Each edge is given
    350   some *context* and a *check* to be performed as well as an AML *program*
    351   which determines the *outcome*.  We generally distinguish between
    352   "original" measures (defined globally in the exchange configuration) and
    353   "custom" measures (defined specifically for an account by AML staff).
    354 
    355 * **Outcome**: An `AmlOutcome` describes the account state that an account
    356   ends up in due to either an AML staff action or an AML *program* doing some
    357   computation over the attributes resulting from a *check*.  Outcomes can be
    358   that certain types of transactions are "verboten", that the account is (or
    359   remains) under investigation by AML staff, that the account is given certain
    360   properties, and/or that certain events are to be logged. Outcomes also
    361   include a new set of *legitimization rules* to apply (and an *expiration*
    362   time at which point a successor *measure* will be automatically taken).
    363 
    364 * **Provider**: A provider performs a specific set of *checks* at a certain
    365   *cost*. Interaction with a provider is performed by provider-specific
    366   *logic*.
    367 
    368 * **Program**: An AML helper *program* is given *context* about the current
    369   state of an account and the attribute data from a *check* to compute the
    370   *outcome*.  For example, a *program* may look at the "PEP" field of a KYC
    371   check and decide if the outcome is to put the account into ``normal`` or
    372   ``held-for-manual-review`` state.  AML programs are always specified
    373   with a fallback *measure* to be taken if the program fails.
    374 
    375 * **Trigger**: A specific transaction that satisfies a **Condition**.
    376 
    377 * **Type of operation**: The operation type determines which Taler-specific
    378   operation has triggered the KYC requirement. We support four types of
    379   operation: withdraw (by customer), deposit (by merchant), P2P receive (by
    380   wallet) and (high) wallet balance.
    381 
    382 
    383 Account owner authentication
    384 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    385 
    386 Access to the KYC SPA (or rather, its account-specific state) is controlled by
    387 a *target token* (which is effectively like a bearer token, except passed
    388 inside the URL).  The *target token* ensures that only the account owner has
    389 access to the KYC processes.  It can be obtained by authenticating using
    390 either the merchant private key or reserve private key, depending on the type
    391 of the account (IBAN or wallet-reserve respectively).
    392 
    393 When we need to authenticate a bank account owner, we will simply require them
    394 to make an outgoing wire transfer into the exchange bank account with a public
    395 key in the wire transfer subject (just like when withdrawing), but augmented
    396 with the string "KYC" so we can distinguish the wire transfer from a regular
    397 withdrawal. Typically, we would put the merchant public key into the wire
    398 transfer subject; wallets MAY put their long-term reserve public key instead.
    399 The amount to be transferred is the *KYC fee*.
    400 
    401 This has several advantages:
    402 
    403 * Only the account owner can provide us with the public key, so we already
    404   have also one super-hard piece of KYC evidence.
    405 * If the account owner looses their public key, it's not a problem: they
    406   would just have to do the transfer again with a new key. No need for
    407   us to do any kind of intervention for key management.
    408 * We could theoretically get paid to do the KYC process, or just "charge" a
    409   nominal amount.
    410 * This also somewhat addresses the payment for voluntary KYC processes where
    411   a merchant wants to do KYC to get us to attest their identity for their
    412   customers even if we do not yet have a legal need.  The only issue here
    413   is that this does not work if voluntary KYC is invoiced while mandatory
    414   KYC is gratis. But, that kind of configuration is a business decision
    415   and there is no hard need to support it immediately.
    416 * This definitively addresses the need for authentication to access the
    417   attestation API, which so far was only available for P2P payments as
    418   we could not authenticate merchants.
    419 * The "KYC" string allows us to distinguish the authentication transfers from
    420   withdrawal transfers; by keeping the KYC fee at or below the closing fee,
    421   we can even deploy this without fully updating the logic everywhere to
    422   distinguish KYC transfers
    423 
    424 
    425 451 Response
    426 ^^^^^^^^^^^^
    427 
    428 When KYC operations are required, various endpoints may respond with a
    429 ``451 Unavailable for Legal Reasons`` status code and a `LegitimizationNeededResponse`
    430 body.
    431 
    432 New endpoints
    433 ^^^^^^^^^^^^^
    434 
    435 .. http:get:: /kyc-check/$H_PAYTO
    436 
    437   Checks the KYC status of a particular payment target and possibly begins a
    438   KYC process by allowing the customer to choose the next KYC measure to
    439   satisfy. This endpoint is typically used by wallets or merchants that
    440   have been told that a transaction is not happening because it triggered
    441   some KYC/AML measure and now want to check how the KYC/AML
    442   requirement could be fulfilled (or whether it already has been
    443   statisfied and the operation can now proceed).  Long-polling may be used
    444   to instantly observe a change in the KYC requirement status.
    445 
    446   The payto hash of the ``/kyc-check/`` endpoint encodes the
    447   account (or wallet) for which legitimization measures are determined.
    448   It is returned in `LegitimizationNeededResponse` responses as in
    449   the case of withdraw, the wallet may not know the debited bank account.
    450 
    451   Given a valid pair of payto hash and account owner signature, the
    452   ``/kyc-check/`` endpoint returns either just the KYC status or redirects the
    453   client (202) to the next required stage of the KYC process.  The redirection
    454   must be for an HTTP(S) endpoint to be triggered via a simple HTTP GET.  It
    455   must always be the same endpoint for the same client, as the wallet/merchant
    456   backend are not required to check for changes to this endpoint.  Clients
    457   that received a 202 status code may repeat the request and use long-polling
    458   to detect a change of the HTTP status.
    459 
    460   **Request:**
    461 
    462   *Account-Owner-Signature*:
    463 
    464     The client must provide Base-32 encoded EdDSA signature with
    465     ``$ACCOUNT_PRIV``, affirming the desire to obtain KYC data.  Note that
    466     this is merely a simple authentication mechanism, the details of the
    467     request are not protected by the signature.  The ``$ACCOUNT_PRIV`` is
    468     either the (wallet long-term) reserve private key or the merchant instance
    469     private key.
    470 
    471   :query timeout_ms=NUMBER: *Optional.*  If specified, the exchange will
    472     wait up to ``timeout_ms`` milliseconds if the requirement continues
    473     to be mandatory provisioning of KYC data by the client.
    474     Ignored if the HTTP status code is already ``200 Ok``.  Note that
    475     clients cannot long-poll for AML staff actions, so status information
    476     about an account being under AML review needs to be requested
    477     periodically.
    478 
    479   **Response:**
    480 
    481   :http:statuscode:`200 Ok`:
    482     No mandatory KYC actions are required by the client at this time.
    483     The client *may* still visit the KYC URL to initiate voluntary checks.
    484     The response will be an `AccountKycStatus` object which specifies
    485     restrictions that currently apply to the account. If the
    486     client attempts to exceed *soft* limits, the status may change
    487     to a ``202 Accepted``.  Hard limits cannot be lifted by passing KYC checks.
    488   :http:statuscode:`202 Accepted`:
    489     The account holder performed an operation that would have crossed
    490     *soft* limits and must be redirected to the provided location to perform
    491     the required KYC checks to satisfy the legal requirements. Afterwards, the
    492     ``/kyc-check/`` request should be repeated to check whether the
    493     user has completed the process.
    494     The response will be an `AccountKycStatus` object.
    495   :http:statuscode:`204 No content`:
    496     The exchange is not configured to perform KYC and thus
    497     the legal requirements are already satisfied.
    498   :http:statuscode:`403 Forbidden`:
    499     The provided signature is not acceptable for the payto hash.
    500   :http:statuscode:`404 Not found`:
    501     The requirement row is unknown.
    502 
    503 .. http:get:: /aml-spa/$FILENAME
    504 
    505   Serves the resources of the AML SPA.
    506 
    507 .. http:get:: /kyc-spa/$FILENAME
    508 
    509   Serves the resources of the KYC SPA. Note that
    510   ``$FILENAME`` must be syntactically distinct from
    511   the access token.  Any ``$ACCESS_TOKEN`` will be
    512   mapped internally to "index.html".
    513 
    514 .. http:get:: /kyc-spa/$ACCESS_TOKEN
    515 
    516   A set of ``/kyc-spa/$ACCESS_TOKEN`` GET endpoints is created per account
    517   hash that serves the KYC SPA.  This is where the ``/kyc-check/`` endpoint
    518   will in principle redirect clients.  The KYC SPA will use the
    519   ``$ACCESS_TOKEN`` of its URL to initialize itself via the
    520   ``/kyc-info/$ACCESS_TOKEN`` endpoint family.  The KYC SPA may download
    521   additional resources via ``/kyc-spa/$FILENAME``. The filenames must not
    522   match base32-encoded 256-bit values.
    523 
    524 .. http:get:: /kyc-info/$ACCESS_TOKEN
    525 
    526   The ``/kyc-info/$ACCESS_TOKEN`` endpoints are created per client
    527   account hash (but access controlled via a unique target token)
    528   to return information about the state of the KYC or AML process
    529   to the KYC SPA.  The SPA uses this information to show the user an
    530   appropriate dialog. The SPA should also long-poll this endpoint for changes
    531   to the AML/KYC state. Note that this is a client-facing endpoint, so it will
    532   only provide a restricted amount of information to the customer (as some
    533   laws may forbid us to inform particular customers about their true status).
    534   The endpoint will typically inform the SPA about possible choices to
    535   proceed, such as directly uploading files, contacting AML staff, or
    536   proceeding with a particular KYC process at an external provider (such as
    537   Challenger).  If the user chooses to initate a KYC process at an external
    538   provider, the SPA must request the respective process to be set-up by the
    539   exchange via the ``/kyc-start/`` endpoint.
    540 
    541   **Request:**
    542 
    543   *If-None-Match*:
    544     The client MAY provide an ``If-None-Match`` header with an ETag.
    545 
    546   :query timeout_ms=MILLISECONDS:
    547     *Optional.* If specified, the exchange will wait up to MILLISECONDS for
    548     a change to a more recent legitimization measure before returning a 304
    549     Not Modified status.
    550 
    551   **Response:**
    552 
    553   *Etag*: Will be set to the serial ID of the measure. Used for long-polling (only for 200 OK responses).
    554 
    555   :http:statuscode:`200 OK`:
    556     The body is a `KycProcessClientInformation`.
    557   :http:statuscode:`204 No Content`:
    558     There are no open KYC requirements or possible voluntary checks
    559     the client might perform.
    560   :http:statuscode:`304 Not Modified`:
    561     The KYC requirements did not change.
    562 
    563 
    564 .. http:post:: /kyc-upload/$ID
    565 
    566   The ``/kyc-upload/$ID`` POST endpoint allows the SPA to upload
    567   client-provided evidence.  The ``$ID`` will be provided as part of the
    568   ``/kyc-info`` body.  This is for checks of type ``FORM``.  In practice,
    569   ``$ID`` will encode both the ``$ACCESS_TOKEN`` and the index of the selected
    570   measure (but this should be irrelevant for the client).
    571 
    572   **Request:**
    573 
    574   Basically oriented along the possible formats of a HTTP form being
    575   POSTed. Details will depend on the form. The server will try to decode the
    576   uploaded body from whatever format it is provided in.
    577 
    578   **Response:**
    579 
    580   :http:statuscode:`204 No Content`:
    581     The information was successfully uploaded. The SPA should fetch
    582     an updated ``/kyc-info/``.
    583   :http:statuscode:`404 Not Found`:
    584     The ``$ID`` is unknown to the exchange.
    585   :http:statuscode:`409 Conflict`:
    586     The upload conflicts with a previous upload.
    587   :http:statuscode:`413 Request Entity Too Large`:
    588     The body is too large.
    589 
    590 .. http:post:: /kyc-start/$ID
    591 
    592   The ``/kyc-start/$ID`` POST endpoint allows the SPA to set up a new external
    593   KYC process. It will return the URL that the client must GET to begin the
    594   KYC process. The SPA should probably open this URL in a new window or tab.
    595   The ``$ID`` will be provided as part of the ``/kyc-info`` body.  In
    596   practice, ``$ID`` will encode both the ``$ACCESS_TOKEN`` and the index of
    597   the selected measure (but this should be irrelevant for the client).
    598 
    599   **Request:**
    600 
    601   Use empty JSON body for now.
    602 
    603   **Response:**
    604 
    605   :http:statuscode:`200 Ok`:
    606     The KYC process was successfully initiated. The URL is in a
    607     `KycProcessStartInformation` object.
    608 
    609   :http:statuscode:`404 Not Found`:
    610     The ``$ID`` is unknown to the exchange.
    611 
    612   .. note::
    613 
    614     As this endpoint is involved in every KYC check at the beginning, this
    615     is also the place where we could integrate the payment process for the KYC fee
    616     in the future (since **vATTEST**).
    617 
    618 
    619 .. http:get:: /kyc-proof/$PROVIDER_SECTION?state=$H_PAYTO
    620 
    621   Upon completion of the process at the external KYC provider, the provider
    622   must redirect the client (browser) to trigger a GET request to a new
    623   ``/kyc-proof/$H_PAYTO/$PROVIDER_SECTION`` endpoint.  Once this endpoint is
    624   triggered, the exchange will pass the received arguments to the respective
    625   logic plugin.  The logic plugin will then (asynchronously) update the KYC
    626   status of the user.  The logic plugin should redirect the user to the KYC
    627   SPA. This endpoint deliberately does not use the ``$ACCESS_TOKEN`` as the
    628   external KYC provider should not learn that token.
    629 
    630   This endpoint is thus accessed from the user's browser at the *end* of a KYC
    631   process, possibly providing the exchange with additional credentials to
    632   obtain the results of the KYC process.  Specifically, the URL arguments
    633   should provide information to the exchange that allows it to verify that the
    634   user has completed the KYC process. The details depend on the logic, which
    635   is selected by the "$PROVIDER_SECTION".
    636 
    637   While this is a GET (and thus safe, and idempotent), the operation may
    638   actually trigger significant changes in the exchange's state.  In
    639   particular, it may update the KYC status of a particular payment target.
    640 
    641   **Request:**
    642 
    643   Details on the request depend on the specific KYC logic that was used.
    644 
    645   If the KYC plugin logic is OAuth 2.0, the query parameters are:
    646 
    647   :query code=CODE:
    648      OAuth 2.0 code argument.
    649   :query state=STATE:
    650      OAuth 2.0 state argument with the H_PAYTO.
    651 
    652   .. note::
    653 
    654     Depending on the OAuth variant used, additional
    655     query parameters may need to be passed here.
    656 
    657   **Response:**
    658 
    659   Given that the response is returned to a user using a browser and **not** to
    660   a Taler wallet, the response format is in human-readable HTML and not in
    661   machine-readable JSON.
    662 
    663   :http:statuscode:`302 Found`:
    664     The KYC operation succeeded and the
    665     payment target is now authorized to transact.
    666     The browser is redirected to a human-readable
    667     page configured by the exchange operator.
    668   :http:statuscode:`401 Unauthorized`:
    669     The provided authorization token is invalid.
    670   :http:statuscode:`404 Not found`:
    671     The payment target is unknown.
    672   :http:statuscode:`502 Bad Gateway`:
    673     The exchange received an invalid reply from the
    674     legitimization service.
    675   :http:statuscode:`504 Gateway Timeout`:
    676     The exchange did not receive a reply from the legitimization
    677     service within a reasonable time period.
    678 
    679 
    680 .. http:get:: /kyc-webhook/$PROVIDER_SECTION/*
    681 .. http:post:: /kyc-webhook/$PROVIDER_SECTION/*
    682 .. http:get:: /kyc-webhook/$LOGIC/*
    683 .. http:post:: /kyc-webhook/$LOGIC/*
    684 
    685   Alternatively, the KYC confirmation may be triggered by a ``/kyc-webhook``
    686   request. As KYC **providers** do not necessarily support passing detailed
    687   information in the URL arguments, the ``/kyc-webhook`` only needs to specify
    688   either the ``PROVIDER_SECTION`` *or* the ``LOGIC`` (the name of the plugin
    689   implementing the KYC API).  The API-specific webhook logic must then figure
    690   out what exactly the webhook is about on its own.  The ``/kyc-webhook/``
    691   endpoint works for GET or POST, again as details depend on the KYC provider.
    692   In contrast to ``kyc-proof``, the response does NOT go to the end-users'
    693   browser and should thus only indicate success or failure.
    694 
    695   **Request:**
    696 
    697   Details on the request depend on the specific KYC logic that was used.
    698 
    699   **Response:**
    700 
    701   :http:statuscode:`204 No content`:
    702     The operation succeeded.
    703   :http:statuscode:`404 Not found`:
    704     The specified logic is unknown.
    705 
    706 
    707 .. http:post:: /kyc-wallet
    708 
    709   The ``/kyc-wallet`` POST endpoint allows a wallet to notify an exchange if
    710   it will cross a balance threshold.  Here, the ``balance`` specified should be
    711   the threshold (from the ``wallet_balance_limit_without_kyc`` array) that the
    712   wallet would cross, and *not* the *exact* balance of the wallet.  The exchange
    713   will respond with a wire target UUID. The wallet can then use this UUID to
    714   being the KYC process at ``/kyc-check/``. The wallet must only proceed to
    715   obtain funds exceeding the threshold after the KYC process has concluded.
    716   While wallets could be "hacked" to bypass this measure (we cannot
    717   cryptographically enforce this), such modifications are a terms of service
    718   violation which may have legal consequences for the user.
    719 
    720   Setup KYC identification for a wallet.  Returns the KYC UUID.  This endpoint
    721   is used by compliant Taler wallets when they are about to hit the balance
    722   threshold and thus need to have the customer provide their personal details
    723   to the exchange.  The wallet is identified by its long-lived reserve public
    724   key (which is used for P2P payments, not for withdrawals).
    725 
    726   **Request:**
    727 
    728   The request body must be a `WalletKycRequest` object.
    729 
    730   **Response:**
    731 
    732   :http:statuscode:`204 No Content`:
    733     KYC is disabled at this exchange, or the balance is below the
    734     threshold that requires KYC, or this wallet already satisfied
    735     the KYC check for the given balance.
    736   :http:statuscode:`403 Forbidden`:
    737     The provided signature is invalid.
    738     This response comes with a standard `ErrorDetail` response.
    739   :http:statuscode:`451 Unavailable for Legal Reasons`:
    740     The wallet must undergo a KYC check. A KYC ID was created.
    741     The response will be a `LegitimizationNeededResponse` object.
    742 
    743 .. http:get:: /aml/$OFFICER_PUB/measures
    744 
    745   To enable the AML staff SPA to give AML staff a choice of possible measures, a
    746   new endpoint ``/aml/$OFFICER_PUB/measures`` is added that allows the AML SPA
    747   to dynamically GET the list of available measures.  It returns a list of known
    748   KYC checks (by name) with their descriptions and a list of AML programs with
    749   information about the required context.
    750 
    751   **Request:**
    752 
    753   *Taler-AML-Officer-Signature*:
    754     The client must provide Base-32 encoded EdDSA signature with
    755     ``$OFFICER_PRIV``, affirming the desire to obtain AML data.  Note that
    756     this is merely a simple authentication mechanism, the details of the
    757     request are not protected by the signature.
    758 
    759   **Response:**
    760 
    761   :http:statuscode:`200 Ok`:
    762     Information about possible measures is returned in a
    763     `AvailableMeasureSummary` object.
    764 
    765 .. http:get:: /aml/$OFFICER_PUB/kyc-statistics/$NAME
    766 
    767   Returns the number of KYC events matching the given event type ``$NAME`` in
    768   the specified time range.  Note that this query can be slow as the
    769   statistics are computed on-demand. (This is OK as such requests should be
    770   rare.)
    771 
    772   **Request:**
    773 
    774   *Taler-AML-Officer-Signature*:
    775     The client must provide Base-32 encoded EdDSA signature with
    776     ``$OFFICER_PRIV``, affirming the desire to obtain AML data.  Note that this
    777     is merely a simple authentication mechanism, the details of the request are
    778     not protected by the signature.
    779 
    780   :query start_date=TIMESTAMP:
    781     *Optional*. Specifies the date when to
    782     start looking (inclusive). If not given, the start time of the
    783     exchange operation is used.
    784   :query end_date=TIMESTAMP:
    785     *Optional*. Specifies the date when to
    786     stop looking (exclusive). If not given, the current date is used.
    787 
    788   **Response:**
    789 
    790   :http:statuscode:`200 OK`:
    791     The response will be an `EventCounter` message.
    792 
    793 .. http:get:: /aml/$OFFICER_PUB/decisions
    794 
    795   **Request:**
    796 
    797   *Taler-AML-Officer-Signature*:
    798     The client must provide Base-32 encoded EdDSA signature with
    799     ``$OFFICER_PRIV``, affirming the desire to obtain AML data.  Note that
    800     this is merely a simple authentication mechanism, the details of the
    801     request are not protected by the signature.
    802 
    803   :query limit:
    804     *Optional*. takes value of the form ``N (-N)``, so that at
    805     most ``N`` values strictly older (younger) than ``start`` are returned.
    806     Defaults to ``-20`` to return the last 20 entries (before ``start``).
    807   :query offset:
    808     *Optional*. Row number threshold, see ``delta`` for its
    809     interpretation.  Defaults to ``INT64_MAX``, namely the biggest row id
    810     possible in the database.
    811   :query h_payto:
    812     *Optional*. Account selector. All matching accounts are returned if this
    813     filter is absent, otherwise only decisions for this account.
    814   :query active:
    815     *Optional*. If set to yes, only return active decisions, if no only
    816     decisions that have been superceeded. Do not give (or use "all") to
    817     see all decisions regardless of activity status.
    818   :query investigation:
    819     *Optional*. If set to yes, only return accounts that are under
    820     AML investigation, if no only accounts that are not under investigation.
    821     Do not give (or use "all") to see all accounts regardless of
    822     investigation status.
    823 
    824   **Response:**
    825 
    826   :http:statuscode:`200 OK`:
    827     The response will be an `AmlDecisionsResponse` message.
    828   :http:statuscode:`204 No content`:
    829     There are no matching AML records.
    830   :http:statuscode:`403 Forbidden`:
    831     The signature is invalid.
    832   :http:statuscode:`404 Not found`:
    833     The designated AML account is not known.
    834   :http:statuscode:`409 Conflict`:
    835     The designated AML account is not enabled.
    836 
    837 .. http:get:: /aml/$OFFICER_PUB/attributes/$H_PAYTO
    838 
    839   Obtain attributes obtained as part of AML/KYC processes for a
    840   given account.
    841 
    842   **Request:**
    843 
    844   *Taler-AML-Officer-Signature*:
    845     The client must provide Base-32 encoded EdDSA signature with
    846     ``$OFFICER_PRIV``, affirming the desire to obtain AML data.  Note that
    847     this is merely a simple authentication mechanism, the details of the
    848     request are not protected by the signature.
    849 
    850   :query limit:
    851     *Optional*. takes value of the form ``N (-N)``, so that at
    852     most ``N`` values strictly older (younger) than ``start`` are returned.
    853     Defaults to ``-20`` to return the last 20 entries (before ``start``).
    854   :query offset:
    855     *Optional*. Row number threshold, see ``delta`` for its
    856     interpretation.  Defaults to ``INT64_MAX``, namely the biggest row id
    857     possible in the database.
    858 
    859   **Response:**
    860 
    861   :http:statuscode:`200 OK`:
    862     The response will be an `KycAttributes` message.
    863   :http:statuscode:`204 No content`:
    864     There are no matching KYC attributes.
    865   :http:statuscode:`403 Forbidden`:
    866     The signature is invalid.
    867   :http:statuscode:`404 Not found`:
    868     The designated AML account is not known.
    869   :http:statuscode:`409 Conflict`:
    870     The designated AML account is not enabled.
    871 
    872 .. http:post:: /aml/$OFFICER_PUB/decision
    873 
    874   Make an AML decision. Triggers the respective action and
    875   records the justification.
    876 
    877   **Request:**
    878 
    879   The request body must be an `AmlDecisionRequest` message.
    880 
    881   **Response:**
    882 
    883   :http:statuscode:`204 No content`:
    884     The AML decision has been executed and recorded successfully.
    885   :http:statuscode:`403 Forbidden`:
    886     The signature is invalid.
    887   :http:statuscode:`404 Not found`:
    888     The address the decision was made upon is unknown to the exchange or
    889     the designated AML account is not known.
    890   :http:statuscode:`409 Conflict`:
    891     The designated AML account is not enabled or a more recent
    892     decision was already submitted.
    893 
    894 Modifications to existing endpoints
    895 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    896 
    897 When withdrawing, the exchange checks if the KYC status is acceptable.  If no
    898 KYC was done and if either the amount withdrawn over a particular timeframe
    899 exceeds the threshold or the reserve received received a P2P transfer, then a
    900 ``451 Unavailable for Legal Reasons`` is returned which redirects the consumer
    901 to the new ``/kyc-check/`` handler.
    902 
    903 When depositing, the exchange aggregator (!) checks the KYC status and if
    904 negative, returns an additional information field via the
    905 ``aggregation_transient`` table which is returned via GET ``/deposts/`` to the
    906 merchant.
    907 
    908 When merging into a reserve, the KYC status is checked and again the
    909 merge fails with ``451 Unavailable for Legal Reasons`` to trigger the
    910 KYC process.
    911 
    912 To allow the wallet to do the KYC check if it is about to exceed a set balance
    913 threshold, we modify the ``/keys`` response to add an optional array
    914 ``wallet_balance_limit_without_kyc`` of threshold amounts is returned.
    915 Whenever the wallet crosses one of these thresholds for the first time, it
    916 should trigger the KYC process.  If this field is absent, there is no limit.
    917 If the field is provided, a correct wallet must create a long-term
    918 account-reserve key pair. This should be the same key that is also used to
    919 receive wallet-to-wallet payments. Then, *before* a wallet performs an
    920 operation that would cause it to exceed the balance threshold in terms of
    921 funds held from a particular exchange, it *should* first request the user to
    922 complete the KYC process.  For that, the wallet should POST to the new
    923 ``/kyc-wallet`` endpoint, providing its long-term reserve-account public key
    924 and a signature requesting permission to exceed the account limit.
    925 
    926 
    927 Configuration of external KYC providers
    928 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    929 
    930 For each KYC provider that could contribute to checks the configuration
    931 specifies a ``$PROVIDER_SECTION`` for each authentication procedure.  For each
    932 (enabled) provider, the exchange has a logic plugin which (asynchronously)
    933 determines the redirect URL for a given wire target. See below for a
    934 description of the high-level process for different providers.
    935 
    936 .. code-block:: ini
    937 
    938   [kyc-provider-$PROVIDER_ID]
    939 
    940   # Which plugin is responsible for this provider?
    941   LOGIC = PLUGIN_NAME
    942 
    943   # Plus additional logic-specific options, e.g.:
    944   AUTHORIZATION_TOKEN = superdupersecret
    945 
    946   # Other logic-specific internal options (example):
    947   FORM_ID = business_legi_form
    948 
    949 
    950 Configuration of possible KYC/AML checks
    951 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    952 
    953 The configuration specifies a set of possible KYC checks offered by external
    954 providers, one per configuration section:
    955 
    956 .. code-block:: ini
    957 
    958   [kyc-check-$CHECK_NAME]
    959 
    960   # Which type of check is this? Also determines
    961   # the SPA form to show to the user for this check.
    962   #
    963   # INFO: wait for staff or contact staff out-of band
    964   #          (only information shown, no SPA action)
    965   # FORM: SPA should show an inline (HTML) form
    966   # LINK: SPA may start external KYC process or upload
    967   #
    968   TYPE = INFO|LINK|FORM
    969 
    970   # Provider id, present only if type is LINK.
    971   # Refers to a ``kyc-provider-$PROVIDER_ID`` section.
    972   PROVIDER_ID = id
    973 
    974   # Name of the SPA form, if type is FORM
    975   # "INFO" and "LINK" are reserved and must not be used.
    976   # The exchange server and the SPA must agree on a list
    977   # of supported forms and the resulting attributes.
    978   #
    979   # The SPA should include a JSON resource file
    980   # "forms.json" mapping form names to arrays of
    981   # attribute names each form provides.
    982   FORM_NAME = name
    983 
    984   # Descriptions to use in the SPA to display the check.
    985   DESCRIPTION = "Upload your passport picture"
    986   DESCRIPTION_I18N = "{"en":"Upload scan of your passport"}"
    987 
    988   # ';'-separated list of fields that the CONTEXT must
    989   # provide as inputs to this check. For example,
    990   # for a FORM of type CHOICE, this might state
    991   # ``choices: string[];``. The type after the ":"
    992   # is for now purely for documentation and is
    993   # not checked. However, it may be shown to AML staff
    994   # when they configure measures.
    995   REQUIRES = requirement;
    996 
    997   # Description of the outputs provided by the check.
    998   # Basically, the check's output is expected to
    999   # provide the following fields as attribute inputs into
   1000   # a subsequent AML program.
   1001   # Only given for type FORM; INFO never has any outputs,
   1002   # and for type LINK we can obtain the same information
   1003   # from the CONVERTER via ``--list-outputs``.
   1004   OUTPUTS = business_name street city country registration
   1005 
   1006   # **original** measure to take if the check fails
   1007   # (for any reason, e.g. provider or form fail to
   1008   # satisfy constraints or provider signals user error)
   1009   # Usually should point to a measure that requests
   1010   # AML staff to investigate.  The fallback measure
   1011   # context always includes the reasons for the
   1012   # failure.
   1013   FALLBACK = MEASURE_NAME
   1014 
   1015 The list of possible FORM names is fixed in the SPA
   1016 for a particular exchange release.
   1017 
   1018 The outcome of *any* check should always be uploaded encrypted into the
   1019 ``kyc_attributes`` table.  It MUST include an ``expiration_time``.
   1020 
   1021 The "check_name" value "skip" is reserved and must not be defined. It can be
   1022 used in measures where the AML program must be run immediately without any
   1023 input.
   1024 
   1025 
   1026 Configuration of legitimization requirement triggers
   1027 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
   1028 
   1029 The configuration also specifies a set of legitimization rules including the
   1030 condition and the measure the condition triggers, one condition per
   1031 configuration section:
   1032 
   1033 .. code-block:: ini
   1034 
   1035   [kyc-rule-$RULE_NAME]
   1036 
   1037   # Operation that triggers this rule.
   1038   # Must be one of "WITHDRAW", "DEPOSIT",
   1039   # (p2p) "MERGE", (wallet) "BALANCE",
   1040   # (reserve) "CLOSE", "AGGREGATE",
   1041   # "TRANSACTION" or "REFUND".
   1042   OPERATION_TYPE = WITHDRAW
   1043 
   1044   # Space-separated list of next measures to be performed.
   1045   # The SPA should display *all* of these measures to the user.
   1046   # (They have a choice of either which ones, or in
   1047   # which order they are to be performed.)
   1048   # A special measure name "verboten" is used if the
   1049   # specified threshold may never be crossed
   1050   # (under this set of rules).
   1051   NEXT_MEASURES = SWISSNESS KYB
   1052 
   1053   # "YES" if all NEXT_MEASURES will eventually need
   1054   # to be satisfied, "NO" if the user has a choice between
   1055   # them. Not actually enforced by the exchange, but
   1056   # primarily used to inform the user whether this is
   1057   # an "and" or "or". YES for "and".
   1058   IS_AND_COMBINATOR = YES
   1059 
   1060   # YES if the rule (specifically, operation type,
   1061   # threshold, timeframe) and the general nature of
   1062   # the next measure (verboten or approval required)
   1063   # should be exposed to the client.
   1064   # Defaults to NO if not set.
   1065   EXPOSED = YES
   1066 
   1067   # Threshold amount above which the rule is
   1068   # triggered.  The total must be exceeded in the given
   1069   # timeframe.
   1070   THRESHOLD = KUDOS:100
   1071 
   1072   # Timeframe over which the amount to be compared to
   1073   # the THRESHOLD is calculated.
   1074   # Ignored for WALLET-BALANCE.  Can be 'forever'.
   1075   TIMEFRAME = 30 days
   1076 
   1077   # Set to YES to enable the rule (default is NO)
   1078   ENABLED = NO
   1079 
   1080 
   1081 AML programs
   1082 ^^^^^^^^^^^^
   1083 
   1084 AML programs are helper programs that can:
   1085 
   1086 * Generate a list of *required* context field names
   1087   for the helper (introspection!) using the "--required-context"
   1088   command-line switch. The output should use the same
   1089   syntax as the REQUIRES clause of ``[kyc-check-]``
   1090   configuration sections, except that new lines
   1091   MUST be used to separate fields instead of ";".
   1092 * Generate a list of *required* attribute names
   1093   for the helper (introspection!) using the "--required-attributes"
   1094   command-line switch. The output should use the same
   1095   list of names as the ATTRIBUTES in the
   1096   ``[kyc-provider-]`` configuration section
   1097   (but may also include FORM field names).
   1098 * Process an input JSON object of type
   1099   `AmlProgramInput` into a JSON object of
   1100   type `AmlOutcome`.
   1101   This is the default behavior if no command-line switches
   1102   are provided.
   1103 
   1104 If the AML program fails (exits with a failure code or
   1105 does not provide well-formed JSON output) the AML/KYC
   1106 process continues with the FALLBACK measure. This should
   1107 usually be one that asks AML staff to contact the
   1108 systems administrator.
   1109 
   1110 AML programs are listed in the configuration file, one program per section:
   1111 
   1112 .. code-block:: ini
   1113 
   1114   [aml-program-$PROG_NAME]
   1115 
   1116   # Program to run.
   1117   COMMAND = taler-helper-aml-pep
   1118 
   1119   # Human-readable description of what this
   1120   # AML helper program will do. Used to show
   1121   # to the AML staff.
   1122   DESCRIPTION = "check if the customer is a PEP"
   1123 
   1124   # True if this AML program is enabled (and thus can be
   1125   # used in measures and exposed to AML staff).
   1126   # Optional, default is NO.
   1127   ENABLED = YES
   1128 
   1129   # **original** measure to take if COMMAND fails
   1130   # Usually points to a measure that asks AML staff
   1131   # to contact the systems administrator. The fallback measure
   1132   # context always includes the reasons for the
   1133   # failure.
   1134   FALLBACK = MEASURE_NAME
   1135 
   1136 
   1137 Configuration of measures
   1138 ^^^^^^^^^^^^^^^^^^^^^^^^^
   1139 
   1140 Finally, the configuration specifies a set of
   1141 **original** *measures* one per configuration section:
   1142 
   1143 .. code-block:: ini
   1144 
   1145   [kyc-measure-$MEASURE_NAME]
   1146 
   1147   # Possible check for this measure.  Optional.
   1148   # If not given, PROGRAM should be run immediately
   1149   # (on an empty set of attributes).
   1150   CHECK_NAME = IB_FORM
   1151 
   1152   # Context for the check. The context can be
   1153   # just an empty JSON object if there is none.
   1154   CONTEXT = {"choices":["individual","business"]}
   1155 
   1156   # Program name to run on the context and check data to
   1157   # determine the outcome and next measure.
   1158   # Refers to a ``[aml-program-$PROG_NAME]`` section name.
   1159   PROGRAM = taler-aml-program
   1160 
   1161   # Optional. Set to YES to allow this measure to be
   1162   # done voluntarily by a client. Used to offer the
   1163   # KYC SPA to display measure even if they are
   1164   # not required. Default is NO.
   1165   VOLUNTARY = YES/NO
   1166 
   1167 
   1168 If ``CHECK_NAME`` is set to "SKIP" (or is not provided at all), the AML
   1169 ``PROGRAM`` is to be run immediately.  This is useful if no client-interaction
   1170 is required to arrive at a decision.
   1171 
   1172 .. note::
   1173 
   1174   The list of *measures* is not complete: AML staff may freely define new
   1175   measures dynamically, usually by selecting checks, an AML program, and
   1176   providing context.
   1177 
   1178 
   1179 Sanity checking
   1180 ^^^^^^^^^^^^^^^
   1181 
   1182 On start-up, ``taler-exchange-httpd`` should sanity-check its
   1183 configuration. Specifically, it should validate that for all AML programs the
   1184 input requirements (attributes and context) are claimed to be satisfied by the
   1185 respective checks that may trigger those programs, and similarly that for all
   1186 checks the original measures satisfy the context requirements for their KYC
   1187 checks.
   1188 
   1189 As a result, any component (AML program, form or external check) is warranted
   1190 to be always called with the declared required inputs. Furthermore, we can
   1191 detect if a component fails to produce the required output and the
   1192 configuration contains (presumably safe) FALLBACKs to address this case.  The
   1193 exchange *MUST* detect circular failures, like when a FALLBACK triggers a
   1194 measure that itself immediately triggers again the same FALLBACK.
   1195 
   1196 
   1197 Exchange database schema
   1198 ^^^^^^^^^^^^^^^^^^^^^^^^
   1199 
   1200 We introduce a new ``wire_targets`` table into the exchange database. This
   1201 table is referenced as the source or destination of payments (regular deposits
   1202 and also P2P payments).  A positive side-effect is that we reduce duplication
   1203 in the ``reserves_in``, ``wire_out`` and ``deposits`` tables as they can
   1204 reference this table.
   1205 
   1206 We introduce a new ``legitimization_processes`` table that tracks the status
   1207 of a legitimization process at a provider, including the configuration section
   1208 name, the user/account name at the provider, and some legitimization
   1209 identifier for the process at the provider.  In this table, we additionally
   1210 store information related to the KYC status of the underlying payto://-URI, in
   1211 particular when the KYC expires (0 if it was never done).
   1212 
   1213 Finally, we introduce a new ``legitimization_requirements`` table that
   1214 contains a list of checks required for a particular wire target.  When KYC is
   1215 triggered (say when some endpoint returns an HTTP status code of 451) a
   1216 new requirement is first put into the requirements table. Then, when the
   1217 client identifies as business or individual the specific legitimization
   1218 process is started.  When the taler-exchange-aggregator triggers a KYC check
   1219 the merchant can observe this when a 202 (Accepted) status code is returned
   1220 on GET ``/deposits/`` with the respective legitimization requirement row.
   1221 
   1222 
   1223 .. sourcecode:: sql
   1224 
   1225   CREATE TABLE wire_targets
   1226     (wire_target_serial_id BIGSERIAL UNIQUE
   1227     ,wire_target_h_payto BYTEA PRIMARY KEY CHECK (LENGTH(wire_target_h_payto)=32),
   1228     ,access_token BYTEA UNIQUE CHECK (LENGTH(access_token)=32) DEFAULT gen_random_bytes(32)
   1229     ,target_pub BYTEA CHECK (LENGTH(target_pub)=32) DEFAULT NULL
   1230     ,payto_uri STRING NOT NULL
   1231     )
   1232     PARTITION BY HASH (wire_target_h_payto);
   1233 
   1234   COMMENT ON TABLE wire_targets
   1235     IS 'All recipients of money via the exchange';
   1236   COMMENT ON COLUMN wire_targets.h_payto
   1237     IS 'Unsalted hash of payto_uri';
   1238   COMMENT ON COLUMN wire_targets.access_token
   1239     IS 'high-entropy random value that is used as a token to authorize access to the KYC process (without requiring a signature by target_priv)';
   1240   COMMENT ON COLUMN wire_targets.target_pub
   1241     IS 'Public key (reserve_pub or merchant_pub) associated with the account; NULL if KYC is not allowed for the account (if there was no incoming KYC wire transfer yet); updated, thus NOT available to the auditor';
   1242   COMMENT ON COLUMN wire_targets.payto_uri
   1243     IS 'Can be a regular bank account, or also be a URI identifying a reserve-account (for P2P payments)';
   1244 
   1245   CREATE TABLE IF NOT EXISTS legitimization_measures
   1246     (legitimization_measure_serial_id INT8 GENERATED BY DEFAULT AS IDENTITY
   1247     ,access_token BYTEA NOT NULL UNIQUE CHECK (LENGTH(access_token)=32)
   1248      REFERENCES wire_targets (access_token)
   1249     ,start_time INT8 NOT NULL
   1250     ,jmeasures TEXT NOT NULL
   1251     ,display_priority INT4 NOT NULL
   1252     ,is_finished BOOL NOT NULL DEFAULT(FALSE)
   1253     )
   1254     PARTITION BY HASH (access_token);
   1255 
   1256   COMMENT ON TABLE legitimization_measures
   1257     IS 'Rules that have been triggered for the account (FIXME: check this is consistent with usage)';
   1258   COMMENT ON COLUMN legitimization_measures.access_token
   1259     IS 'Used to uniquely identify the account and as a symmetric access control mechanism for the SPA';
   1260   COMMENT ON COLUMN legitimization_measures.start_time
   1261     IS 'Time when the measure was triggered (by decision or rule)';
   1262   COMMENT ON COLUMN legitimization_measures.jmeasures
   1263     IS 'JSON object of type LegitimizationMeasures with KYC/AML measures for the account encoded';
   1264   COMMENT ON COLUMN legitimization_measures.display_priority
   1265     IS 'Display priority of the rule that triggered this measure; if in the meantime another rule also triggers, the measure is only replaced if the new rule has a higher display priority';
   1266   COMMENT ON COLUMN legitimization_measures.is_finished
   1267     IS 'Set to TRUE if this set of measures was processed; used to avoid indexing measures that are done';
   1268 
   1269   CREATE INDEX ON legitimization_measures (access_token)
   1270     WHERE NOT is_finished;
   1271 
   1272   CREATE TABLE legitimization_outcomes
   1273     (outcome_serial_id INT8 GENERATED BY DEFAULT AS IDENTITY
   1274     ,h_payto BYTEA CHECK (LENGTH(h_payto)=32)
   1275      REFERENCES wire_targets (wire_target_h_payto)
   1276     ,decision_time INT8 NOT NULL DEFAULT(0)
   1277     ,expiration_time INT8 NOT NULL DEFAULT(0)
   1278     ,jproperties TEXT,
   1279     ,new_measure_name TEXT,
   1280     ,to_investigate BOOL NOT NULL
   1281     ,is_active BOOL NOT NULL DEFAULT(TRUE)
   1282     ,jnew_rules TEXT NOT NULL
   1283     )
   1284     PARTITION BY HASH (h_payto);
   1285 
   1286   COMMENT ON TABLE legitimization_outcomes
   1287     IS 'Outcomes can come from AML programs';
   1288   COMMENT ON COLUMN legitimization_outcomes.h_payto
   1289     IS 'hash of the payto://-URI this outcome is about';
   1290   COMMENT ON COLUMN legitimization_outcomes.decision_time
   1291     IS 'when was this outcome decided';
   1292   COMMENT ON COLUMN legitimization_outcomes.expiration_time
   1293     IS 'time when the decision expires and the expiration jnew_rules should be applied';
   1294   COMMENT ON COLUMN legitimization_outcomes.jproperties
   1295     IS 'JSON object of type AccountProperties, such as PEP status, business domain, risk assessment, etc.';
   1296   COMMENT ON COLUMN legitimization_outcomes.to_investigate
   1297     IS 'AML staff should investigate the activity of this account';
   1298   COMMENT ON COLUMN legitimization_outcomes.is_active
   1299     IS 'TRUE if this is the current authoritative legitimization outcome';
   1300   COMMENT ON COLUMN legitimization_outcomes.new_measure_name
   1301     IS 'space-separated list of measures to trigger immediately, NULL for none, prefixed with a "+" to indicate AND combination for the measures';
   1302   COMMENT ON COLUMN legitimization_outcomes.jnew_rules
   1303     IS 'JSON object of type LegitimizationRuleSet with rules to apply to the various operation types for this account; all KYC checks should first check if active new rules for a given account exist in this table (and apply specified measures); if not, it should check the default rules to decide if a measure is required';
   1304 
   1305   CREATE INDEX legitimization_outcomes_active
   1306     ON legitimization_outcomes(h_payto)
   1307     WHERE is_active;
   1308 
   1309   CREATE TABLE legitimization_processes
   1310     (legitimization_process_serial_id BIGSERIAL UNIQUE
   1311     ,h_payto BYTEA NOT NULL CHECK (LENGTH(h_payto)=64)
   1312      REFERENCES wire_targets (wire_target_h_payto)
   1313     ,start_time INT8 NOT NULL
   1314     ,expiration_time INT8 NOT NULL DEFAULT (0)
   1315     ,legitimization_measure_serial_id INT8
   1316      REFERENCES legitimization_measures (legitimization_measure_serial_id)
   1317     ,measure_index INT4
   1318     ,provider_section TEXT NOT NULL
   1319     ,provider_user_id TEXT DEFAULT NULL
   1320     ,provider_legitimization_id TEXT DEFAULT NULL
   1321     ,redirect_url TEXT DEFAULT NULL
   1322     ,finished BOOLEAN DEFAULT (FALSE)
   1323     )
   1324     PARTITION BY HASH (h_payto);
   1325 
   1326   COMMENT ON TABLE legitimization_processes
   1327     IS 'here we track KYC processes we initiated with external providers; the main reason is so that we do not initiate a second process when an equivalent one is still active; note that h_payto, provider_section, jcontext must match and the process must not be finished or expired for an existing redirect_url to be re-used; given that clients may voluntarily initiate KYC processes, there may not always be a legitimization_measure that triggered the setup';
   1328   COMMENT ON COLUMN legitimization_processes.h_payto
   1329     IS 'foreign key linking the entry to the wire_targets table, NOT a primary key (multiple KYC setups are possible per wire target)';
   1330   COMMENT ON COLUMN legitimization_processes.start_time
   1331     IS 'when was the legitimization process initiated';
   1332   COMMENT ON COLUMN legitimization_processes.expiration_time
   1333     IS 'when does the process expire (and needs to be manually set up again)';
   1334   COMMENT ON COLUMN legitimization_processes.measure_index
   1335     IS 'index of the measure in legitimization_measures that was selected for this KYC setup; NULL if legitimization_measure_serial_id is NULL; enables determination of the context data provided to the external process';
   1336   COMMENT ON COLUMN legitimization_processes.provider_section
   1337     IS 'Configuration file section with details about this provider';
   1338   COMMENT ON COLUMN legitimization_processes.provider_user_id
   1339     IS 'Identifier for the user at the provider that was used for the legitimization. NULL if provider is unaware.';
   1340   COMMENT ON COLUMN legitimization_processes.provider_legitimization_id
   1341     IS 'Identifier for the specific legitimization process at the provider. NULL if legitimization was not started.';
   1342   COMMENT ON COLUMN legitimization_processes.legitimization_measure_serial_id
   1343     IS 'measure that enabled this setup, NULL if client voluntarily initiated the process';
   1344   COMMENT ON COLUMN legitimization_processes.redirect_url
   1345     IS 'Where the user should be redirected for this external KYC process';
   1346   COMMENT ON COLUMN legitimization_processes.finished
   1347     IS 'set to TRUE when the specific legitimization process is finished';
   1348 
   1349   CREATE TABLE kyc_attributes
   1350     (kyc_attributes_serial_id INT8 GENERATED BY DEFAULT AS IDENTITY
   1351     ,h_payto BYTEA PRIMARY KEY CHECK (LENGTH(h_payto)=32)
   1352      REFERENCES wire_targets (wire_target_h_payto)
   1353     ,legitimization_process_serial_id INT8
   1354      REFERENCES legitimization_processes (legitimization_process_serial_id)
   1355      DEFAULT NULL
   1356     ,collection_time INT8 NOT NULL
   1357     ,expiration_time INT8 NOT NULL
   1358     ,trigger_outcome_serial INT8 NOT NULL
   1359      REFERENCES legitimization_outcomes(outcome_serial_id)
   1360     ,encrypted_attributes BYTEA NOT NULL
   1361     ) PARTITION BY HASH (h_payto);
   1362 
   1363   COMMENT ON COLUMN kyc_attributes.h_payto
   1364     IS 'identifies the account this is about';
   1365   COMMENT ON COLUMN kyc_attributes.legitimization_process_serial_id
   1366     IS 'serial ID of the legitimization process that resulted in these attributes, NULL if the attributes are from a form directly supplied by the account owner via a form';
   1367   COMMENT ON COLUMN kyc_attributes.collection_time
   1368     IS 'when were these attributes collected';
   1369   COMMENT ON COLUMN kyc_attributes.expiration_time
   1370     IS 'when are these attributes expected to expire';
   1371   COMMENT ON COLUMN kyc_attributes.trigger_outcome_serial
   1372     IS 'ID of the outcome that was returned by the AML program based on the KYC data collected';
   1373   COMMENT ON COLUMN kyc_attributes.encrypted_attributes
   1374     IS 'encrypted JSON object with the attribute data the check provided';
   1375 
   1376   CREATE TABLE aml_history
   1377     (aml_history_serial_id INT8 GENERATED BY DEFAULT AS IDENTITY
   1378     ,h_payto BYTEA CHECK (LENGTH(h_payto)=32)
   1379      REFERENCES wire_targets (wire_target_h_payto)
   1380     ,outcome_serial_id INT8 NOT NULL
   1381      REFERENCES legitimization_outcomes (outcome_serial_id)
   1382     ,justification TEXT NOT NULL
   1383     ,decider_pub BYTEA CHECK (LENGTH(decider_pub)=32)
   1384     ,decider_sig BYTEA CHECK (LENGTH(decider_sig)=64);
   1385 
   1386   COMMENT ON TABLE aml_history
   1387     IS 'Records decisions by AML staff with the respective signature and free-form justification.';
   1388   COMMENT ON COLUMN aml_history.outcome_serial_id
   1389     IS 'Actual outcome for the account (included in what decider_sig signs over)';
   1390   COMMENT ON COLUMN aml_history.decider_sig
   1391     IS 'Signature key of the staff member affirming the AML decision; of type AML_DECISION';
   1392 
   1393   CREATE TABLE kyc_events
   1394     (kyc_event_serial_id INT8 GENERATED BY DEFAULT AS IDENTITY
   1395     ,event_timestamp INT8 NOT NULL
   1396     ,event_type TEXT NOT NULL);
   1397 
   1398   COMMENT ON TABLE kyc_events
   1399     IS 'Records of key events for statistics. Populated via triggers.';
   1400   COMMENT ON COLUMN kyc_events.event_type
   1401     IS 'Name of the event, such as account-open or sar-filed';
   1402 
   1403   CREATE INDEX kyc_event_index
   1404     ON kyc_events(event_type,event_timestamp);
   1405 
   1406 
   1407 The ``jmeasures`` JSON in the ``legitimization_measures``
   1408 table is of type `LegitimizationMeasures`.
   1409 
   1410 The ``jnew_rules`` JSON in the ``legitimization_outcomes``
   1411 table is of type `LegitimizationRuleSet`.
   1412 
   1413 The ``jproperties`` JSON in the ``legitimization_outcomes`` table is of
   1414 type `AccountProperties`.
   1415 
   1416 
   1417 KYC forms
   1418 ^^^^^^^^^
   1419 
   1420 The KYC SPA run by clients needs to support three TYPEs of checks. INFO is
   1421 only about displaying the provided information, LINK is about setting up an
   1422 exteral KYC check and redirecting there. FORM is about displaying a particular
   1423 (HTML) form to the user and POSTing the entered information directly with the
   1424 exchange.  Here we describe the forms that must be supported:
   1425 
   1426 * **CHOICE**: Asks the client a multiple-choice question.  The context must
   1427   include "choices: string[]" with a list of choices to show.  Used, for
   1428   example, to ask a client if they are an individual or a business.  The
   1429   resulting HTML FORM field name must be "choice" and it must be mapped to
   1430   strings from the choices list.
   1431 
   1432 * **UPLOAD**: Asks the client to upload a single file.
   1433   The context must include a ``validity_duration`` which
   1434   will be converted to the ``expiration_time`` for
   1435   the uploaded data.  The context may furthermore include
   1436   ``extensions?: string[]`` with a list of allowed file extensions the client's
   1437   file must end with (e.g. "png", "pdf", "gif").  In the absence of this
   1438   context, any file may be uploaded.  The context may also include a
   1439   ``size_limit?: Integer`` with the maximum file size in bytes that can be
   1440   uploaded.  The resulting HTTP POST should provide at least two fields, "filename" and
   1441   "filedata".  "filename" must be set to the basename of the original file (to
   1442   the extend that it is available), and "filedata" to the base64-encoding of
   1443   the uploaded data.
   1444 
   1445 As with other SPA checks, the KYC form should also show
   1446 the description of the check.
   1447 
   1448 
   1449 Merchant modifications
   1450 ^^^^^^^^^^^^^^^^^^^^^^
   1451 
   1452 A new setting is required where the merchant backend can be configured for a
   1453 business (default) or individual.
   1454 
   1455 We introduce new ``kyc_ok``, ``aml_decision``, ``kyc_timestamp`` and
   1456 ``exchange_kyc_serial`` fields into a new table ``merchant_kyc`` with primary
   1457 keys ``exchange_url`` and ``account_serial``.  This status is updated whenever
   1458 a deposit is created or tracked, or whenever the mechant backend receives a
   1459 ``/kyc-check/`` response from the exchange.  Initially,
   1460 ``exchange_kyc_serial`` is zero, indicating that the merchant has not yet made
   1461 any deposits and thus does not have an account at the exchange.
   1462 
   1463 A new private endpoint ``/kyc`` is introduced which allows frontends to
   1464 request the ``/kyc`` status of any configured account (including with long
   1465 polling).  If the KYC status is negative or the ``kyc_timestamp`` not recent
   1466 (say older than one month), the merchant backend will re-check the KYC status
   1467 at the exchange (and update its cached status).  The endpoint then returns
   1468 either that the KYC is OK, or information (same as from the exchange endpoint)
   1469 to begin the KYC process.
   1470 
   1471 The merchant backend uses the new field to remember that a KYC is pending
   1472 (after detection in ``taler-merchant-depositcheck``) and the SPA then shows a
   1473 notification whenever the staff is logged in to the system.  The notification
   1474 can be hidden for the current day (remembered in local storage).
   1475 
   1476 The notification links to a (new) KYC status page. When opened, the KYC SPA
   1477 first re-checks the KYC status with the exchange.  If the KYC is still
   1478 unfinished, that SPA will show forms, links or contact information to begin
   1479 the KYC process (for example, redirecting to the OAuth 2.0 login page of the
   1480 legitimization resource server), otherwise it shows that the KYC process is
   1481 done. If the KYC is unfinished, the merchant SPA should use long-polling on
   1482 the KYC status on this page to ensure it is always up-to-date, and change to
   1483 ``KYC satisfied`` should the long-poller return with positive news.
   1484 
   1485   ..note::
   1486 
   1487     Semi-related: The TMH_setup_wire_account() is changed to use
   1488     128-bit salt values (to keep ``deposits`` table small) and checks for salt
   1489     to be well-formed should be added "everywhere".
   1490 
   1491 
   1492 
   1493 Bank requirements
   1494 ^^^^^^^^^^^^^^^^^
   1495 
   1496 The exchange primarily requires a KYC provider to be operated by the
   1497 bank that offers an endpoint for with an API implemented by one of
   1498 the logic plugins (and the respective legitimization configuration).
   1499 
   1500 
   1501 Logic plugins
   1502 ^^^^^^^^^^^^^
   1503 
   1504 The ``$PROVIDER_SECTION`` is based on the name of the configuration section,
   1505 not on the name of the logic plugin (that we call ``$LOGIC``).  Using the
   1506 configuration section, the exchange then determines the logic plugin to use.
   1507 
   1508 This section describes the general API for all of the supported KYC providers,
   1509 as well as some details of how this general API could be implemented by the
   1510 logic for different APIs.
   1511 
   1512 
   1513 General KYC Logic Plugin API
   1514 ----------------------------
   1515 
   1516 This section provides a sketch of the proposed API for the KYC logic plugins.
   1517 
   1518 * initiation of KYC check (``kyc-check``):
   1519 
   1520   - inputs:
   1521     + provider_section (for additional configuration)
   1522     + h_payto
   1523   - outputs:
   1524     + success/provider-failure
   1525     + redirect URL (or NULL)
   1526     + provider_user_id (or NULL)
   1527     + provider_legitimization_id (or NULL)
   1528 
   1529 * KYC status check (``kyc-proof``):
   1530 
   1531   - inputs:
   1532     + provider_section (for additional configuration)
   1533     + h_payto
   1534     + provider_user_id (or NULL)
   1535     + provider_legitimization_id (or NULL)
   1536   - outputs:
   1537     + success/pending/user-aborted/user-failure/provider-failure status code
   1538     + HTML response for end-user
   1539 
   1540 * Webhook notification handler (``kyc-webhook``):
   1541 
   1542   - inputs:
   1543     + HTTP method (GET/POST)
   1544     + rest of URL (after provider_section)
   1545     + HTTP body (if applicable!)
   1546   - outputs:
   1547     + success/pending/user-aborted/user-failure/provider-failure status code
   1548     + h_payto (for DB status update)
   1549     + HTTP response to be returned to KYC provider
   1550 
   1551 The plugins do not directly interact with the database, the caller sets the
   1552 expiration on ``success`` and also updates ``provider_user_id`` and
   1553 ``provider_legitimization_id`` in the tables as required.
   1554 
   1555 
   1556 For the webhook, we need a way to lookup ``h_payto`` by other data, so the
   1557 KYC logic plugin API should be provided a method lookup with:
   1558 
   1559   - inputs:
   1560     + ``provider_section``
   1561     + ``provider_legitimization_id``
   1562   - outputs:
   1563     + ``h_payto``
   1564     + ``legitimization_process_row``
   1565 
   1566 
   1567 OAuth 2.0 specifics
   1568 -------------------
   1569 
   1570 In terms of configuration, the OAuth 2.0 logic requires the respective client
   1571 credentials to be configured apriori to enable access to the legitimization
   1572 service.
   1573 
   1574 For the ``/kyc-check/`` endpoint, the OAuth 2.0 logic may need to create and
   1575 store a nonce to be used during ``/kyc-proof/``, depending on the OAuth
   1576 variant used.  This may require another exchange table.  The OAuth 2.0 process
   1577 must then be set up to end at the new ``/kyc-proof/$PROVIDER_ID/`` endpoint.
   1578 
   1579 This ``/kyc-proof/oauth2/`` endpoint must query the OAuth 2.0 server using the
   1580 ``code`` argument provided as a query parameter. Based on the result, it then
   1581 updates the KYC table of the exchange with the legitimization status and
   1582 returns a human-readable KYC status page.
   1583 
   1584 The ``/kyc-webhook/`` is not applicable.
   1585 
   1586 
   1587 Persona specifics
   1588 -----------------
   1589 
   1590 We would use the hosted flow. Endpoints return a ``request-id``, which we should
   1591 log for diagnosis.
   1592 
   1593 For ``/kyc-check/``:
   1594 
   1595 * Post to ``/api/v1/accounts`` using ``reference-id`` set to our ``h_payto``.
   1596   Returns ``id`` (account_id).
   1597 
   1598 * Create ``/verify`` endpoint using ``template-id`` (from configuration),
   1599   and ``account_id`` (from previous step) and a ``reference-id`` (use
   1600   the ``legitimization_serial_id`` for the new process). Set
   1601   ``redirect-uri`` to ``/kyc-proof/$PROVIDER_ID/``.  However, we cannot
   1602   rely on the user clicking this, so we must also configure a webhook.
   1603   The request returns a '``verification-id``.  That we store under
   1604   the ``provider_legitimization_id`` in the database.
   1605 
   1606 For ``/kyc-proof/``:
   1607 
   1608 * Use the ``/api/v1/verifications`` endpoint to get the verification
   1609   status. Requires the ``verification-id`` from the previous step.
   1610   Results include: created/pending/completed/expired (aborted)/failed.
   1611 
   1612 For ``/kyc-webhook/``:
   1613 
   1614 * The webhook is authenticated using a shared secret, which should
   1615   be in the configuration.  So all we should have to do is parse
   1616   the POSTed body to find the status and the ``verification-id`` to
   1617   lookup ``h_payto`` and return the result.
   1618 
   1619 
   1620 KYC AID specifics
   1621 -----------------
   1622 
   1623 For ``/kyc-check/``:
   1624 
   1625 * Post to ``/applicants`` with a type (person or company) to
   1626   obtain ``applicant_id``. Store that under ``provider_user_id``.
   1627   ISSUE: *we* need to get the company_name, business_activity_id
   1628   and registration_country before this somehow!
   1629 
   1630 * start with create form URL ``/forms/$FORM_ID/urls``
   1631   providing our ``h_payto`` as the ``external_applicant_id``,
   1632   using the ``applicant_id`` from above,
   1633   and the ``/kyc-proof/$PROVIDER_ID`` for the ``redirect_url``.
   1634 
   1635 * redirect customer to the ``form_url``,
   1636   store the ``verification_id`` under ``provider_legitimization_id``
   1637   in the database.
   1638 
   1639 For ``/kyc-proof/``:
   1640 
   1641 * Not needed, just return an error.
   1642 
   1643 For ``/kyc-webhook/``:
   1644 
   1645 * For security, we should probably simply trigger the GET on
   1646   ``/verifications/{verification_id}`` to not trust an unsigned POST
   1647   to tell us anything for sure.  The result is then returned.
   1648 
   1649 
   1650 Types of KYC events
   1651 ^^^^^^^^^^^^^^^^^^^
   1652 
   1653 The ``/aml/$OFFICER_PUB/kyc-statistics`` endpoint exposes statistics for
   1654 various KYC event types.
   1655 
   1656 We will initially support the use of the following types of KYC events in the
   1657 SPA (and have a dialog to show the total number of any of these for any
   1658 specified time range):
   1659 
   1660 * account-open
   1661 * account-closed
   1662 * voluntary-sar
   1663 * mandatory-sar
   1664 * pep-started
   1665 * pep-ended
   1666 * risky-started
   1667 * risky-ended
   1668 * account-frozen
   1669 * account-unfrozen
   1670 
   1671 Based on these, the SPA should also be albe to show active
   1672 statistics (for any given timestamp) on the total number of:
   1673 
   1674 * open accounts
   1675 * frozen accounts
   1676 * high-risk accounts
   1677 * PEPs served
   1678 
   1679 .. note::
   1680 
   1681    This can be done by simply running the queries with
   1682    a start time of zero and subtracting.
   1683 
   1684 
   1685 Alternatives
   1686 ============
   1687 
   1688 We could also store the access token (returned by OAuth 2.0), but that seems
   1689 slightly more dangerous and given the close business relationship is
   1690 unnecessary. Furthermore, not all APIs offer this.
   1691 
   1692 We could extend the KYC logic API to return key attributes about the user
   1693 (such as legal name, phone number, address, etc.) which we could then sign and
   1694 return to the user.  This would be useful in P2P payments to identify the
   1695 origin of an invoice.  However, we might want to be careful to not disclose
   1696 the key attributes via the API by accident.  This could likely be done by
   1697 limiting access to the respective endpoint to messages with a signature by the
   1698 reserve private key (which is the only case where we care to certify things
   1699 anyway).
   1700 
   1701 
   1702 Drawbacks
   1703 =========
   1704 
   1705 
   1706 Discussion / Q&A
   1707 ================
   1708 
   1709 (This should be filled in with results from discussions on mailing lists / personal communication.)
   1710 
   1711 
   1712 If you have questions, remarks or suggestions regarding this information,
   1713 please feel free to leave a comment at our
   1714 `TALER Integration Community Hub <https://ich.taler.net/t/gnu-taler-exchange-documentation/78>`_.