summaryrefslogtreecommitdiff
path: root/design-documents
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2024-04-19 23:00:29 +0200
committerChristian Grothoff <christian@grothoff.org>2024-04-19 23:00:29 +0200
commitc0c26e784726a9e4ab5f1cf14f99c3d8312c19ea (patch)
tree2acc99ff9ab2e925f472524cf90845b536194cc5 /design-documents
parent0fc5dd62d57b722bb1e2b29fc99aa919d6c89324 (diff)
downloaddocs-c0c26e784726a9e4ab5f1cf14f99c3d8312c19ea.tar.gz
docs-c0c26e784726a9e4ab5f1cf14f99c3d8312c19ea.tar.bz2
docs-c0c26e784726a9e4ab5f1cf14f99c3d8312c19ea.zip
update kYC spec
Diffstat (limited to 'design-documents')
-rw-r--r--design-documents/023-taler-kyc.rst361
1 files changed, 293 insertions, 68 deletions
diff --git a/design-documents/023-taler-kyc.rst b/design-documents/023-taler-kyc.rst
index 77dbe2bb..e6addbdd 100644
--- a/design-documents/023-taler-kyc.rst
+++ b/design-documents/023-taler-kyc.rst
@@ -178,8 +178,9 @@ For the user-interactive checks we need a SPA (for KYC) that is given:
* instructions to render (with either a form to fill or links to external checks);
here the context could provide an array of choices!
-* possibly an external check that was set up (if any); for cost-reasons, we should only do one at a time,
- and probably should then always redirect the browser to that check.
+* possibly an external check that was set up (if any); for cost-reasons, we
+ should only do one at a time, and probably should then always redirect the
+ browser to that check.
For the staff-interactive checks we need a SPA (for AML):
@@ -213,31 +214,69 @@ documents.
Terminology
^^^^^^^^^^^
-* **Check**: A check establishes a particular attribute of a user, such as their name based on an ID document and lifeness, mailing address, phone number, taxpayer identity, etc. Checks may be given *context* (such as whether a customer is an individual or a business) to run correctly. Checks can also be AML staff inserting information for plausibilization. Checks result in an *outcome* being decided by an external AML *program*.
-
-* **Condition**: A condition specifies when KYC is required. Conditions include the *type of operation*, a threshold amount (e.g. above EUR:1000) and possibly a time period (e.g. over the last month).
-
-* **Configuration**: The configuration determines the *legitimization rules*, and specifies which providers offer which *checks* at what *cost*.
-
-* **Context**: Context is information provided as input into a *check* and *program* to customize their execution. The context is initially set by the *trigger*, but may evolve as the *account* undergoes *measures*. For each *check* and *program*, the required *context* data must be specified.
-
-* **Cost**: How much would a client have to pay for a KYC process (if they voluntarily choose to do so for attestation).
-
-* **Expiration**: KYC legitimizations may be outdated. Expiration rules determine when *checks* have to be performed again.
-
-* **Legitimization rules**: The legitimization rules determine under which *conditions* which *checks* must be performend and the *expiration* time period for the *checks*.
-
-* **Logic**: Logic refers to a specific bit of code (realized as an exchange plugin) that enables the interaction with a specific *provider*. Logic typically requires *configuration* for access control (such as an authorization token) and possibly the endpoint of the specific *provider* implementing the respective API.
-
-* **Measure**: Describes the possible outgoing edges from one state in the state machine (including how to show the current state). Each edge is given some *context* and a *check* to be performed as well as a *program* to decide the *outcome* and the next *measure*.
-
-* **Outcome**: Describes the account state that an account ends up in due to the result of a *check*. Outcomes can be that an account is frozen (no transactions possible until freeze expires), held (no transactions possible until another *measure* has been taken), or operating normally. Outcomes also include a new set of *legitimization rules* to apply and an expiration time at which point a new *measure* will be automatically taken. Finally, parts of the outcome may be explained to the client (for example, to allow a wallet to stay below hard withdraw thresholds).
-
-* **Provider**: A provider performs a specific set of *checks* at a certain *cost*. Interaction with a provider is performed by provider-specific *logic*.
-
-* **Program**: An AML helper *program* is given *context* about the current state of an account and the attribute data from a *check* to compute the *outcome*. For example, a *program* may look at the "PEP" field of a KYC check and decide if the outcome is to put the account into ``normal`` or ``held-for-manual-review`` state.
-
-* **Type of operation**: The operation type determines which Taler-specific operation has triggered the KYC requirement. We support four types of operation: withdraw (by customer), deposit (by merchant), P2P receive (by wallet) and (high) wallet balance.
+* **Check**: A check establishes a particular attribute of a user, such as
+ their name based on an ID document and lifeness, mailing address, phone
+ number, taxpayer identity, etc. Checks may be given *context* (such as
+ whether a customer is an individual or a business) to run correctly. Checks
+ can also be AML staff inserting information for plausibilization. Checks
+ result in an *outcome* being decided by an external AML *program*.
+
+* **Condition**: A condition specifies when KYC is required. Conditions
+ include the *type of operation*, a threshold amount (e.g. above EUR:1000)
+ and possibly a time period (e.g. over the last month).
+
+* **Configuration**: The configuration determines the *legitimization rules*,
+ and specifies which providers offer which *checks* at what *cost*.
+
+* **Context**: Context is information provided as input into a *check* and
+ *program* to customize their execution. The context is initially set by the
+ *trigger*, but may evolve as the *account* undergoes *measures*. For each
+ *check* and *program*, the required *context* data must be specified.
+
+* **Cost**: How much would a client have to pay for a KYC process (if they
+ voluntarily choose to do so for attestation).
+
+* **Expiration**: KYC legitimizations may be outdated. Expiration rules
+ determine when *checks* have to be performed again.
+
+* **Legitimization rules**: The legitimization rules determine under which
+ *conditions* which *checks* must be performend and the *expiration* time
+ period for the *checks*.
+
+* **Logic**: Logic refers to a specific bit of code (realized as an exchange
+ plugin) that enables the interaction with a specific *provider*. Logic
+ typically requires *configuration* for access control (such as an
+ authorization token) and possibly the endpoint of the specific *provider*
+ implementing the respective API.
+
+* **Measure**: Describes the possible outgoing edges from one state in the
+ state machine (including how to show the current state). Each edge is given
+ some *context* and a *check* to be performed as well as a *program* to
+ decide the *outcome* and the next *measure*.
+
+* **Outcome**: Describes the account state that an account ends up in due to
+ the result of a *check*. Outcomes can be that an account is frozen (no
+ transactions possible until freeze expires), held (no transactions possible
+ until another *measure* has been taken), or operating normally. Outcomes
+ also include a new set of *legitimization rules* to apply and an expiration
+ time at which point a new *measure* will be automatically taken. Finally,
+ parts of the outcome may be explained to the client (for example, to allow a
+ wallet to stay below hard withdraw thresholds).
+
+* **Provider**: A provider performs a specific set of *checks* at a certain
+ *cost*. Interaction with a provider is performed by provider-specific
+ *logic*.
+
+* **Program**: An AML helper *program* is given *context* about the current
+ state of an account and the attribute data from a *check* to compute the
+ *outcome*. For example, a *program* may look at the "PEP" field of a KYC
+ check and decide if the outcome is to put the account into ``normal`` or
+ ``held-for-manual-review`` state.
+
+* **Type of operation**: The operation type determines which Taler-specific
+ operation has triggered the KYC requirement. We support four types of
+ operation: withdraw (by customer), deposit (by merchant), P2P receive (by
+ wallet) and (high) wallet balance.
451 Response
@@ -273,7 +312,7 @@ body.
}
-New Endpoints
+New endpoints
^^^^^^^^^^^^^
.. http:get:: /kyc-check/$REQUIREMENT_ROW
@@ -859,8 +898,11 @@ New Endpoints
Note that this is merely a simple authentication mechanism, the details of
the request are not protected by the signature.
- :query start_date=TIMESTAMP: *Optional*. Specifies the date when to start looking (inclusive). If not given, the start time of the exchange operation is used.
- :query end_date=TIMESTAMP: *Optional*. Specifies the date when to stop looking (exclusive). If not given, the current date is used.
+ :query start_date=TIMESTAMP: *Optional*. Specifies the date when to
+ start looking (inclusive). If not given, the start time of the
+ exchange operation is used.
+ :query end_date=TIMESTAMP: *Optional*. Specifies the date when to
+ stop looking (exclusive). If not given, the current date is used.
**Response**:
@@ -869,7 +911,206 @@ New Endpoints
interface EventCounter {
// Number of events of the specified type in
// the given range.
- cnt: Integer;
+ counter: Integer;
+ }
+
+.. http:get:: /aml/$OFFICER_PUB/decisions/$STATE
+
+ Obtain list of AML decisions (filtered by $STATE). ``$STATE`` must be
+ either ``normal``, ``pending`` or ``frozen``.
+
+ *Taler-AML-Officer-Signature*: The client must provide Base-32 encoded EdDSA
+ signature with ``$OFFICER_PRIV``, affirming the desire to obtain AML data.
+ Note that this is merely a simple authentication mechanism, the details of
+ the request are not protected by the signature.
+
+ :query limit: *Optional*. takes value of the form ``N (-N)``, so that at
+ most ``N`` values strictly older (younger) than ``start`` are returned.
+ Defaults to ``-20`` to return the last 20 entries (before ``start``).
+ :query offset: *Optional*. Row number threshold, see ``delta`` for its
+ interpretation. Defaults to ``INT64_MAX``, namely the biggest row id
+ possible in the database.
+
+ **Response**
+
+ :http:statuscode:`200 OK`:
+ The responds will be an `AmlRecords` message.
+ :http:statuscode:`204 No content`:
+ There are no matching AML records.
+ :http:statuscode:`403 Forbidden`:
+ The signature is invalid.
+ :http:statuscode:`404 Not found`:
+ The designated AML account is not known.
+ :http:statuscode:`409 Conflict`:
+ The designated AML account is not enabled.
+
+ **Details:**
+
+ .. ts:def:: AmlRecords
+
+ interface AmlRecords {
+
+ // Array of AML records matching the query.
+ records: AmlRecord[];
+ }
+
+ .. ts:def:: AmlRecord
+
+ interface AmlRecord {
+
+ // Which payto-address is this record about.
+ // Identifies a GNU Taler wallet or an affected bank account.
+ h_payto: PaytoHash;
+
+ // What is the current AML state.
+ current_state: Integer;
+
+ // Monthly transaction threshold before a review will be triggered
+ threshold: Amount;
+
+ // Row ID of the record. Used to filter by offset.
+ rowid: Integer;
+
+ }
+
+
+.. http:get:: /aml/$OFFICER_PUB/decision/$H_PAYTO
+
+ Obtain deails about an AML decision.
+
+ *Taler-AML-Officer-Signature*: The client must provide a Base-32
+ encoded EdDSA signature with ``$OFFICER_PRIV``, affirming the
+ desire to obtain AML data. Note that this is merely a simple
+ authentication mechanism, the details of the request are not
+ protected by the signature.
+
+ :query history: *Optional*. If set to yes, we return all historic
+ decisions for the account, and not only the last one.
+
+ **Response**
+
+ :http:statuscode:`200 OK`:
+ The responds will be an `AmlDecisionDetails` message.
+ :http:statuscode:`204 No content`:
+ There are no matching AML records for the given payto://-URI.
+ :http:statuscode:`403 Forbidden`:
+ The signature is invalid.
+ :http:statuscode:`404 Not found`:
+ The designated AML account is not known.
+ :http:statuscode:`409 Conflict`:
+ The designated AML account is not enabled.
+
+ **Details:**
+
+ .. ts:def:: AmlDecisionDetails
+
+ interface AmlDecisionDetails {
+
+ // Array of AML decisions made for this account. Possibly
+ // contains only the most recent decision if "history" was
+ // not set to 'true'.
+ aml_history: AmlDecisionDetail[];
+
+ // Array of KYC attributes and outcomes obtained for this
+ // account.
+ kyc_attributes: KycDetail[];
+ }
+
+ .. ts:def:: AmlDecisionDetail
+
+ interface AmlDecisionDetail {
+
+ // What was the justification given?
+ justification: string;
+
+ // When does the outcome expire?
+ expiration_time: Timestamp;
+
+ // KYC rules to apply. Note that this
+ // overrides *all* of the default rules
+ // until the ``expiration_time`` and specifies
+ // the successor measure to apply after the
+ // expiration time.
+ new_rules: LegitimizationRules;
+
+ // When was this decision made?
+ decision_time: Timestamp;
+
+ // Who made the decision?
+ decider_pub: AmlOfficerPublicKeyP;
+
+ }
+
+ .. ts:def:: KycDetail
+
+ interface KycDetail {
+
+ // Name of the configuration section that specifies the provider
+ // which was used to collect the KYC details
+ provider_section: string;
+
+ // The collected KYC data. NULL if the attribute data could not
+ // be decrypted (internal error of the exchange, likely the
+ // attribute key was changed).
+ attributes?: Object;
+
+ // Time when the KYC data was collected
+ collection_time: Timestamp;
+
+ // Outcome of the AML program.
+ outcome: AmlProgramOutcome;
+
+ }
+
+
+ .. http:post:: /aml/$OFFICER_PUB/decision
+
+ Make an AML decision. Triggers the respective action and
+ records the justification.
+
+ **Request:**
+
+ The request must be an `AmlDecision` message.
+
+ **Response**
+
+ :http:statuscode:`204 No content`:
+ The AML decision has been executed and recorded successfully.
+ :http:statuscode:`403 Forbidden`:
+ The signature is invalid.
+ :http:statuscode:`404 Not found`:
+ The address the decision was made upon is unknown to the exchange or
+ the designated AML account is not known.
+ :http:statuscode:`409 Conflict`:
+ The designated AML account is not enabled or a more recent
+ decision was already submitted.
+
+ **Details:**
+
+ .. ts:def:: AmlDecision
+
+ interface AmlDecision {
+
+ // Human-readable justification for the decision.
+ justification: string;
+
+ // Which payto-address is the decision about?
+ // Identifies a GNU Taler wallet or an affected bank account.
+ h_payto: PaytoHash;
+
+ // When does the outcome expire?
+ expiration_time: Timestamp;
+
+ // What are the new rules?
+ new_rules: LegitimizationRules;
+
+ // When was the decision made?
+ decision_time: Timestamp;
+
+ // Signature by the AML officer over a `TALER_AmlDecisionPS`.
+ // Must have purpose ``TALER_SIGNATURE_MASTER_AML_KEY``.
+ officer_sig: EddsaSignature;
+
}
@@ -1125,14 +1366,10 @@ AML programs are helper programs that can:
// JSON array with the results of historic
// AML desisions about the account.
- // FIXME: review AmlDecisionDetail spec!
- // (need to enable new outcomes!)
aml_history: AmlDecisionDetail[];
// JSON array with the results of historic
// KYC data about the account.
- // FIXME: review KycDetail spec!
- // (need to include AmlProgramOutcome!)
kyc_history: KycDetail[];
}
@@ -1167,20 +1404,12 @@ AML programs are helper programs that can:
// When does the outcome expire?
expiration_time: Timestamp;
- // Name of the measure to apply the outcome expires.
- // If not set, we revert to the default set
- // of rules (and the default account state).
- successor_measure?: string;
-
- // Array of KYC rules to apply. Note that this
- // array overrides *all* of the default rules.
- // Thus, if the array does not have an entry for
- // a particular operation, there would be
- // no thresholds for that operation!
- rules: KycRule[];
-
- // Custom measures that KYC rules may refer to.
- custom_measures?: { "name" : MeasureInformation };
+ // KYC rules to apply. Note that this
+ // overrides *all* of the default rules
+ // until the ``expiration_time`` and specifies
+ // the successor measure to apply after the
+ // expiration time.
+ new_rules: LegitimizationRules;
}
@@ -1596,25 +1825,21 @@ exteral KYC check and redirecting there. FORM is about displaying a particular
(HTML) form to the user and POSTing the entered information directly with the
exchange. Here we describe the forms that must be supported:
-* CHOICE: Asks the client a multiple-choice question.
- The context must include "choices: string[]" with
- a list of choices to show. Used, for example, to
- ask a client if they are an individual or a business.
- The resulting HTML FORM field name must be
- "choice" and it must be mapped to strings from the
- choices list.
-* UPLOAD: Asks the client to upload a single file.
- The context may include "extensions: string[]" with
- a list of allowed file extensions the client's file
- must end with (e.g. "png", "pdf", "gif"). In the
- absence of this context, any file may be uploaded.
- The context may also include "size_limit: Integer" with
- the maximum file size in bytes that can be uploaded.
- The resulting HTML FORM must have two fields,
- "filename" and "filedata". "filename" must be
- set to the basename of the original file (to the
- extend that it is available), and "filedata"
- to the base64-encoding of the uploaded data.
+* **CHOICE**: Asks the client a multiple-choice question. The context must
+ include "choices: string[]" with a list of choices to show. Used, for
+ example, to ask a client if they are an individual or a business. The
+ resulting HTML FORM field name must be "choice" and it must be mapped to
+ strings from the choices list.
+
+* **UPLOAD**: Asks the client to upload a single file. The context may include
+ "extensions: string[]" with a list of allowed file extensions the client's
+ file must end with (e.g. "png", "pdf", "gif"). In the absence of this
+ context, any file may be uploaded. The context may also include
+ "size_limit: Integer" with the maximum file size in bytes that can be
+ uploaded. The resulting HTML FORM must have two fields, "filename" and
+ "filedata". "filename" must be set to the basename of the original file (to
+ the extend that it is available), and "filedata" to the base64-encoding of
+ the uploaded data.
As with other SPA checks, the KYC form should also show
the description of the check.