summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2024-04-19 15:00:08 +0200
committerChristian Grothoff <christian@grothoff.org>2024-04-19 15:00:08 +0200
commit51f17bc444a8604253e22c55d09e59c1f871f563 (patch)
treed437e3baad1368e28c67d82adfb30049e4bcff78
parentb61c23faa8c619595e642c4a902f51ad7bb2f060 (diff)
downloaddocs-51f17bc444a8604253e22c55d09e59c1f871f563.tar.gz
docs-51f17bc444a8604253e22c55d09e59c1f871f563.tar.bz2
docs-51f17bc444a8604253e22c55d09e59c1f871f563.zip
improve KYC spec
-rw-r--r--design-documents/023-taler-kyc.rst180
1 files changed, 95 insertions, 85 deletions
diff --git a/design-documents/023-taler-kyc.rst b/design-documents/023-taler-kyc.rst
index c41a3695..6ace74cb 100644
--- a/design-documents/023-taler-kyc.rst
+++ b/design-documents/023-taler-kyc.rst
@@ -46,6 +46,13 @@ Taler needs to take *measures* based on the following primary *triggers*:
* Import of new sanctions lists and triggering of measures against matches of existing
customer records against the list
+For the different operation types, there can be both soft
+and hard limits. Soft limits are those that the customer
+may raise by providing data and passing KYC checks.
+Hard limits cannot be lifted, for example because an
+exchange forbids crossing those limits in its terms of
+service for all customers.
+
Process requirements
^^^^^^^^^^^^^^^^^^^^
@@ -239,66 +246,63 @@ New Endpoints
.. http:get:: /kyc-check/$REQUIREMENT_ROW/$H_PAYTO
Checks the KYC status of a particular payment target and possibly begins the
- KYC process. This endpoint is used by wallets or merchants that have been
- told about a KYC requirement and now want to check if the KYC requirement
- has been fulfilled. Long-polling may be used to instantly observe a change
- in the KYC requirement status.
-
- The ``/kyc-check/`` endpoint is based on the legitimization requirements
- serial number. FIXME: is this still OK?
-
- 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 triplet, the
- ``/kyc-check/`` endpoint returns either the (positive) KYC status or redirects
- the client (202) to the next required stage of the KYC process. The
- redirection must be for an HTTP(S) endpoint to be triggered via a simple HTTP
- GET. It must always be the same endpoint for the same client, as the
- wallet/merchant backend are not required to check for changes to this
- endpoint.
+ KYC process. This endpoint is typically used by wallets or merchants that
+ have been told about a KYC requirement and now want to check if the KYC
+ requirement has been fulfilled. Long-polling may be used to instantly
+ observe a change in the KYC requirement status.
+
+ The ``/kyc-check/`` endpoint is based on the legitimization measure's
+ serial number. It is returned in `KycNeededRedirect` responses via
+ the ``requirement_row`` field together with the ``h_payto``.
+ Access is *authenticated* by also passing the hash of the payto://-URI.
+ .. note::
+
+ Weak authentication is acceptable, as the KYC status or the ability to
+ initiate a KYC process are not very sensitive.
-FIXME: update /kyc-check/ endpoint to expose *public* outcomes of previous
-checks (such as hard withdrawal limits)!
+ Given a valid pair of requirement row and payto-hash, the ``/kyc-check/``
+ endpoint returns either just the KYC status or redirects the client (202) to
+ the next required stage of the KYC process. The redirection must be for an
+ HTTP(S) endpoint to be triggered via a simple HTTP GET. It must always be
+ the same endpoint for the same client, as the wallet/merchant backend are
+ not required to check for changes to this endpoint. Clients that received a
+ 202 status code may repeat the request and use long-polling to detect a
+ change of the HTTP status.
**Request:**
:query timeout_ms=NUMBER: *Optional.* If specified, the exchange will
- wait up to ``timeout_ms`` milliseconds if the payment target
- is currently not legitimized. Ignored if the payment target
- is already legitimized. Note that the legitimization would be
- triggered by another request to the same endpoint with a valid
- ``token``.
+ wait up to ``timeout_ms`` milliseconds if the requirement continues
+ to be mandatory provisioning of KYC data by the client.
+ Ignored if the HTTP status code is already `200 Ok`. Note that
+ clients cannot long-poll for AML staff actions, so status information
+ about an account being under AML review needs to be requested
+ periodically.
**Response:**
:http:statuscode:`200 Ok`:
- The KYC operation succeeded, the exchange confirms that the
- payment target already authorized to transact.
- The response will be an `AccountKycStatus` object.
+ No mandatory KYC actions are required by the client at this time.
+ The client *may* still visit the KYC URL to initiate voluntary checks.
+ The response will be an `AccountKycStatus` object which specifies
+ restrictions that currently apply to the account. If the
+ client attempts to exceed *soft* limits, the status may change
+ to a `202 Accepted`. Hard limits cannot be lifted by passing KYC checks.
:http:statuscode:`202 Accepted`:
- The user should be redirected to the provided location to perform
+ The account holder performed an operation that would have crossed
+ *soft* limits and must be redirected to the provided location to perform
the required KYC checks to satisfy the legal requirements. Afterwards, the
``/kyc-check/`` request should be repeated to check whether the
user has completed the process.
- The response will be an `AccountKycRedirect` object.
+ The response will be an `AccountKycStatus` object.
:http:statuscode:`204 No content`:
The exchange is not configured to perform KYC and thus
the legal requirements are already satisfied.
- :http:statuscode:`402 Payment Required`:
- The client must pay the KYC fee for the KYC process.
- **This is currently not implemented, see #7365.**
:http:statuscode:`403 Forbidden`:
- The provided hash does not match the payment target.
+ The provided hash does not match the requirement row.
:http:statuscode:`404 Not found`:
- The payment target is unknown.
- :http:statuscode:`451 Unavailable for Legal Reasons`:
- The transaction cannot be completed due to AML rules.
- Thus, the operation is currently not stuck on KYC, but
- on exchange staff performing their AML review. The user
- should be told to wait and/or contact the exchange operator
- if the situation persists.
- The response will be a `AccountAmlBlocked` object.
+ The requirement row is unknown.
**Details:**
@@ -306,68 +310,71 @@ checks (such as hard withdrawal limits)!
interface AccountKycStatus {
- // Details about the KYC check that the user
- // passed.
- kyc_details: KycDetails;
-
// Current time of the exchange, used as part of
// what the exchange signs over.
now: Timestamp;
- // EdDSA signature of the exchange affirming the account
- // is KYC'ed, must be of purpose
- // ``TALER_SIGNATURE_EXCHANGE_ACCOUNT_SETUP_SUCCESS``
- // and over ``TALER_AccountSetupStatusSignaturePS``.
- exchange_sig: EddsaSignature;
-
- // public key used to create the signature.
- exchange_pub: EddsaPublicKey;
-
- // Current AML state for the target account. Non-zero
- // values indicate that the transfer is blocked due to
- // AML enforcement.
- aml_status: Integer;
-
- }
-
- .. ts:def:: AccountKycRedirect
-
- interface AccountKycRedirect {
+ // Current AML state for the target account. True if
+ // operations are not happening due to staff processing
+ // paperwork *or* due to legal requirements (so the
+ // client cannot do anything but wait).
+ //
+ // Note that not every AML staff action may be legally
+ // exposed to the client, so this is merely a hint that
+ // a client should be told that AML staff is currently
+ // reviewing the account. AML staff *may* review
+ // accounts without this flag being set!
+ aml_review: boolean;
// URL that the user should open in a browser to
- // proceed with the KYC process.
+ // proceed with the KYC process (optional if
+ // the status type is 200 Ok, mandatory if the
+ // HTTP status is 202 Accepted).
kyc_url: string;
- // Current AML state for the target account. Non-zero
- // values indicate that the transfer is blocked due to
- // AML enforcement.
- aml_status: Integer;
+ // Array with limitations that currently apply to this
+ // account and that may be increased or lifted if the
+ // KYC check is passed.
+ // Note that additional limits *may* exist and not be
+ // communicated to the client. If such limits are
+ // reached, this *may* be indicated by the account
+ // going into ``aml_review`` state. However, it is
+ // also possible that the exchange may legally have
+ // to deny operations without being allowed to provide
+ // any justification.
+ // The limits should be used by the client to
+ // possibly structure their operations (e.g. withdraw
+ // what is possible below the limit, ask the user to
+ // pass KYC checks or withdraw the rest after the time
+ // limit is passed, warn the user to not withdraw too
+ // much or even prevent the user from generating a
+ // request that would cause it to exceed hard limits).
+ limits?: AccountLimit[];
}
- .. ts:def:: AccountAmlBlocked
+ .. ts:def:: AccountLimit
- interface AccountAmlBlocked {
+ interface AccountLimit {
- // Current AML state for the target account. Non-zero
- // values indicate that the transfer is blocked due to
- // AML enforcement.
- aml_status: Integer;
+ // Operation that is limited.
+ // Must be one of "WITHDRAW", "DEPOSIT", "P2P-RECEIVE"
+ // or "WALLET-BALANCE".
+ operation_type: string;
- }
-
- .. ts:def:: KycDetails
-
- // Object that specifies which KYC checks are satisfied.
- interface KycDetails {
+ // Timeframe during which the limit applies.
+ timeframe: RelativeTime;
- // Keys are the names of the check(s).
- // The values are for now always empty objects.
+ // Maximum amount allowed during the given timeframe.
+ // Zero if the operation is simply forbidden.
+ threshold: Amount;
+ // True if this is a soft limit that could be raised
+ // by passing KYC checks.
+ soft: boolean;
}
-
.. http:get:: /kyc-spa/{$HASH,$FILENAME}
A set of ``/kyc-spa/$HASH`` GET endpoints is created per client ``$HASH``
@@ -399,7 +406,9 @@ checks (such as hard withdrawal limits)!
*If-None-Match*: The client MAY provide an ``If-None-Match`` header with
an ETag.
- :query timeout_ms=MILLISECONDS: *Optional.* If specified, the exchange will wait up to MILLISECONDS for a change to a more recent legitimization measure before returning a 304 Not Modified.
+ :query timeout_ms=MILLISECONDS: *Optional.* If specified, the exchange
+ will wait up to MILLISECONDS for a change to a more recent legitimization
+ measure before returning a 304 Not Modified status.
**Response**:
@@ -473,6 +482,7 @@ checks (such as hard withdrawal limits)!
:http:statuscode:`304 Not Modified`:
The KYC requirements did not change.
+
.. http:post:: /kyc-upload/$ID
The ``/kyc-upload/$ID`` POST endpoint allows the SPA to upload