taler-docs

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

commit ad03b8df358653b21081a3a5a93ab6bf5a4f168f
parent 942a9a6ea080b81fc6b8d32682737b5c3820aa52
Author: Christian Grothoff <christian@grothoff.org>
Date:   Sun,  3 May 2026 13:17:07 +0200

fix documentation build issues, start vIMPORT spec for exchange

Diffstat:
M_exts/httpdomain/httpdomain.py | 2+-
Mcore/api-common.rst | 35+++++++++++++++++++++++++++++++++++
Mcore/api-corebank.rst | 2+-
Mcore/api-exchange.rst | 21++++++++-------------
Mcore/api-merchant.rst | 2+-
Mcore/api-sync.rst | 2++
Mcore/donau/post-csr-issue.rst | 2+-
Mcore/exchange/delete-purses-PURSE_PUB.rst | 4++--
Mcore/exchange/get-aml-OFFICER_PUB-accounts.rst | 8++++----
Mcore/exchange/get-aml-OFFICER_PUB-attributes-H_NORMALIZED_PAYTO.rst | 49++++++++++++++++++++++++++++++++++++++++++++++++-
Mcore/exchange/get-aml-OFFICER_PUB-decisions.rst | 4++++
Mcore/exchange/get-aml-OFFICER_PUB-kyc-statistics-NAMES.rst | 4++++
Mcore/exchange/get-aml-OFFICER_PUB-legitimizations.rst | 4++++
Mcore/exchange/get-aml-OFFICER_PUB-measures.rst | 4++++
Mcore/exchange/get-deposits-H_WIRE-MERCHANT_PUB-H_CONTRACT_TERMS-COIN_PUB.rst | 4++--
Mcore/exchange/post-aml-OFFICER_PUB-decision.rst | 10+++++-----
Mcore/exchange/post-batch-deposit.rst | 2+-
Mcore/exchange/post-coins-COIN_PUB-refund.rst | 26++++++++++++++++----------
Acore/exchange/post-kyc-bulk-EXTERN_PUB.rst | 106+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Acore/exchange/post-kyc-import-EXTERN_PUB.rst | 106+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Mcore/exchange/post-reveal-melt.rst | 2+-
Mcore/exchange/post-reveal-withdraw.rst | 6+++++-
Mcore/merchant/get-private-incoming-ID.rst | 2+-
Mcore/merchant/post-instances.rst | 2+-
Mdeployments/tops.rst | 8+++-----
Mdesign-documents/073-extended-merchant-template.rst | 37++-----------------------------------
Mdesign-documents/078-taxes.rst | 3++-
Mdesign-documents/086-wallet-design.rst | 4++--
Mdesign-documents/087-wallet-onboarding.rst | 6++++--
Mlibeufin/nexus-manual.rst | 52++++++++++++++++++++++++++--------------------------
Mtaler-kyc-manual.rst | 2+-
31 files changed, 403 insertions(+), 118 deletions(-)

diff --git a/_exts/httpdomain/httpdomain.py b/_exts/httpdomain/httpdomain.py @@ -211,7 +211,7 @@ HTTP_STATUS_CODES = { 411: 'Length Required', 412: 'Precondition Failed', 413: 'Request Entity Too Large', - 414: 'Request URI Too Long', + 414: 'URI Too Long', 415: 'Unsupported Media Type', 416: 'Requested Range Not Satisfiable', 417: 'Expectation Failed', diff --git a/core/api-common.rst b/core/api-common.rst @@ -1259,6 +1259,14 @@ uses 512-bit hash codes (64 bytes). uint8_t ecdhe_pub[32]; }; +.. _account-pub: +.. sourcecode:: c + + union TALER_AccountPublicKeyP { + struct TALER_ReservePublicKeyP reserve_pub; + struct TALER_MerchantPublicKeyP merchant_pub; + }; + .. _Signatures: Signatures @@ -2371,3 +2379,30 @@ within the struct TALER_ReservePublicKeyP reserve_pub; struct GNUNET_HashCode h_attributes; }; + +.. _TALER_ExternKycDataImportBindingPS: +.. sourcecode:: c + + struct TALER_ExternKycDataImportBindingPS { + /** + * purpose.purpose = TALER_SIGNATURE_EXTERN_KYC_IMPORT_BINDING + */ + struct GNUNET_CRYPTO_EccSignaturePurpose purpose; + struct GNUNET_TIME_AbsoluteNBO import_date; + union GNUNET_AccountPublicKeyP account_pub; + struct GNUNET_HashCode h_attributes; + struct GNUNET_HashCode h_customer_payto; + }; + + +.. _TALER_ExternKycDataBulkBindingPS: +.. sourcecode:: c + + struct TALER_ExternKycDataBulkBindingPS { + /** + * purpose.purpose = TALER_SIGNATURE_EXTERN_KYC_BULK_BINDING + */ + struct GNUNET_CRYPTO_EccSignaturePurpose purpose; + struct GNUNET_HashCode h_body; + struct GNUNET_HashCode h_customer_payto; + }; diff --git a/core/api-corebank.rst b/core/api-corebank.rst @@ -1171,7 +1171,7 @@ Cashouts .. note:: - Consult the `cashout rates call <cashout-rates_>`_ to learn + Consult the `cashout rates call <cashout-rates>`_ to learn about any applicable fee or exchange rate. diff --git a/core/api-exchange.rst b/core/api-exchange.rst @@ -1,6 +1,6 @@ .. This file is part of GNU TALER. - Copyright (C) 2014-2025 Taler Systems SA + Copyright (C) 2014-2026 Taler Systems SA TALER is free software; you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software @@ -51,13 +51,12 @@ The current protocol version is **v34**. * ``vRECOUP``: improved recoup protocol * ``vATTEST``: KYC attestation support +* ``vIMPORT``: external KYC/KYB data import **Ideas for future version:** * ``vXXX``: marker for features not yet targeted for release - - .. include:: tos.rst .. _keys: @@ -122,7 +121,6 @@ Auditor actions This part of the API is for the use by auditors interacting with the exchange. - .. include:: exchange/post-auditors-AUDITOR_PUB-H_DENOM_PUB.rst @@ -139,7 +137,6 @@ for details. .. include:: exchange/post-blinding-prepare.rst - .. _exchange-withdrawal: ---------- @@ -323,7 +320,6 @@ and prove that the age restriction was set correctly. .. include:: exchange/post-reveal-withdraw.rst - ---------- Refreshing ---------- @@ -381,8 +377,8 @@ fee as specified by the coin's denomination. For auctions, a bidder performs an deposit operation and provides all relevant information for the auction policy (such as timeout and public key as bidder) -and can use the ``exchange_sig`` field from the `DepositSuccess` message as a -proof to the seller for the escrow of sufficient fund. +and can use the ``exchange_sig`` field from the `DepositSuccessResponse` +message as a proof to the seller for the escrow of sufficient fund. .. _deposit: @@ -390,7 +386,6 @@ proof to the seller for the escrow of sufficient fund. .. include:: exchange/post-batch-deposit.rst - ------ Recoup ------ @@ -414,11 +409,9 @@ became minted, and proof ownership of the coin itself. .. include:: exchange/post-recoup-withdraw.rst - .. include:: exchange/post-recoup-refresh.rst - .. _exchange_refund: ------- @@ -427,7 +420,6 @@ Refunds .. include:: exchange/post-coins-COIN_PUB-refund.rst - .. _reserve-history: --------------- @@ -437,7 +429,6 @@ Reserve History .. include:: exchange/get-reserves-RESERVE_PUB-history.rst - .. _coin-history: ------------ @@ -1056,6 +1047,10 @@ regulatory compliance. .. include:: exchange/post-kyc-start-ID.rst +.. include:: exchange/post-kyc-import-EXTERN_PUB.rst + +.. include:: exchange/post-kyc-bulk-EXTERN_PUB.rst + .. include:: exchange/get-kyc-proof-PROVIDER_NAME.rst .. include:: exchange/get-kyc-webhook-PROVIDER_NAME-star.rst diff --git a/core/api-merchant.rst b/core/api-merchant.rst @@ -36,7 +36,7 @@ The current protocol version is **v29**. * taler-mdb is currently targeting **v27**. * anastasis is currently targeting **v27**. * taler-woocommerce is currently targeting **vXX**. -* taler-drupal-turnstile is currently targeting **vXX**. +* taler-drupal-turnstile is currently targeting **v29**. * taler-drupal-commerce is currently targeting **vXX**. * paivana is currently targeting **v29**. diff --git a/core/api-sync.rst b/core/api-sync.rst @@ -305,6 +305,8 @@ Uploading Backup Data :http:statuscode:`304 Not modified`: The server is already aware of this version of the client. Returned before ``100 continue`` to avoid upload. + FIXME: Might be better to use ``412 Precondition Failed`` here + in the future! :http:statuscode:`400 Bad request`: Most likely, the uploaded body is too short (less than 32 bytes). diff --git a/core/donau/post-csr-issue.rst b/core/donau/post-csr-issue.rst @@ -21,7 +21,7 @@ One of the referenced donation unit keys could not be found. Returned with error code ``TALER_EC_DONAU_GENERIC_DONATION_UNIT_UNKNOWN``. - :http:statuscode:`500 Internal Server Error`: + :http:statuscode:`500 Internal Server Error`: The donation unit key is not known to the Donau, has the wrong cipher type, or the signing helper encountered an error. Returned with error code ``TALER_EC_DONAU_GENERIC_KEYS_MISSING`` or diff --git a/core/exchange/delete-purses-PURSE_PUB.rst b/core/exchange/delete-purses-PURSE_PUB.rst @@ -7,7 +7,7 @@ The request body must be empty, as recommended for HTTP delete in general. - To authorize the request, the header must contain the following HTTP header: + To authorize the request, the following HTTP headers must be provided: *Taler-Purse-Signature*: $PURSE_SIG`` where ``$PURSE_SIG`` is the Crockford base32-encoded EdDSA @@ -18,7 +18,7 @@ :http:statuscode:`204 No Content`: The operation succeeded, the exchange confirms that the purse was deleted. - :http:statuscode:`400 Bad request`: + :http:statuscode:`400 Bad Request`: The request was malformed. Returned with an error code of ``TALER_EC_EXCHANGE_GENERIC_PURSE_PUB_MALFORMED``. diff --git a/core/exchange/get-aml-OFFICER_PUB-accounts.rst b/core/exchange/get-aml-OFFICER_PUB-accounts.rst @@ -46,9 +46,9 @@ The response will be an `AmlAccountsResponse` message (if the client's header "Accept" was "application/json"). Other encodings may differ in the exact returned data and format. - :http:statuscode:`204 No content`: + :http:statuscode:`204 No Content`: There are no accounts at all (within the specified constraints). - :http:statuscode:`400 Bad request`: + :http:statuscode:`400 Bad Request`: The client's request is malformed. This response comes with a standard `ErrorDetail` response with a code of ``TALER_EC_GENERIC_RESERVE_PUB_MALFORMED``, @@ -60,13 +60,13 @@ The signature is invalid. Returned with a standard `ErrorDetail` response with a code of ``TALER_EC_EXCHANGE_GENERIC_AML_OFFICER_ACCESS_DENIED``. - :http:statuscode:`404 Not found`: + :http:statuscode:`404 Not Found`: The designated AML account is not known. :http:statuscode:`406 Not Acceptable`: The requested MIME type for the response is not supported. This response comes with a standard `ErrorDetail` response with a code of ``TALER_EC_GENERIC_PARAMETER_MALFORMED``. - :http:statuscode:`500 Internal server error`: + :http:statuscode:`500 Internal Server Error`: The server failed to process the request due to an internal error. This response comes with a standard `ErrorDetail` response with a code of ``TALER_EC_GENERIC_DB_FETCH_FAILED``. diff --git a/core/exchange/get-aml-OFFICER_PUB-attributes-H_NORMALIZED_PAYTO.rst b/core/exchange/get-aml-OFFICER_PUB-attributes-H_NORMALIZED_PAYTO.rst @@ -35,18 +35,22 @@ There are no matching KYC attributes. :http:statuscode:`400 Bad Request`: The request is malformed. Cases include: + - The ``$H_NORMALIZED_PAYTO`` or ``H_OFFICER_PUB`` path segment is malformed. This response comes with a standard `ErrorDetail` response with a code of ``TALER_EC_GENERIC_PATH_SEGMENT_MALFORMED``. - The required HTTP header with the signature is missing. Returned with ``TALER_EC_GENERIC_HTTP_HEADERS_MALFORMED``. + :http:statuscode:`403 Forbidden`: Two cases: + - The signature is invalid. Returned with a code of ``TALER_EC_EXCHANGE_GENERIC_AML_OFFICER_GET_SIGNATURE_INVALID``. - The specific officer is unknown or disabled. Returned with a code of ``TALER_EC_EXCHANGE_GENERIC_AML_OFFICER_ACCESS_DENIED``. + :http:statuscode:`404 Not found`: The target account is unknown to the exchange. This response comes with a standard `ErrorDetail` response with @@ -114,6 +118,49 @@ // Attributes can have basically arbitrary additional // Key-value pairs. See the // gnu-taler-form-attributes registry in GANA - // for possible keys! + // for possible keys! For attributes that are + // files, see `KycFileUploadAttribute` and + // `KycBulkUploadAttribute` below. + + } + + .. ts:def:: KycFileUploadAttribute + + // File uploads should always use a single field named + // ``FILE`` with the following nested attributes. + interface KycFileUploadAttribute { + + // Encoded file contents as a string. + CONTENTS: string; + + // Encoding of contents, currently only ``base64`` is supported. + ENCODING: "base64"; + + // Optional name of the file. + FILENAME?: string; + + // MIME type of the uploaded file. + MIME_TYPE: string; + + } + + .. ts:def:: KycBulkUploadAttribute + + // This attribute references a previous bulk file upload + // via the POST ``/kyc-bulk/`` endpoint. + // Bulk uploads should always use a single field named + // ``BULK`` with the following nested attributes. + // Bulk file uploads were introduced in protocol **vIMPORT**. + interface KycBulkUploadAttribute { + + // Reference to the bulk upload via SHA512 hash. + BULK_REF: HashCode; + + // Optional name of the file, required to reference a specific + // file within a ZIP archive where the ZIP was uploaded as a bulk. + FILENAME?: string; + + // MIME type of the referenced file. + MIME_TYPE: string; } diff --git a/core/exchange/get-aml-OFFICER_PUB-decisions.rst b/core/exchange/get-aml-OFFICER_PUB-decisions.rst @@ -40,17 +40,21 @@ There are no matching AML records. :http:statuscode:`400 Bad Request`: The request is malformed. Cases include: + - The ``$H_OFFICER_PUB`` path segment is malformed. This response comes with a standard `ErrorDetail` response with a code of ``TALER_EC_GENERIC_PATH_SEGMENT_MALFORMED``. - The required HTTP header with the signature is missing. Returned with ``TALER_EC_GENERIC_HTTP_HEADERS_MALFORMED``. + :http:statuscode:`403 Forbidden`: Two cases: + - The signature is invalid. Returned with a code of ``TALER_EC_EXCHANGE_GENERIC_AML_OFFICER_GET_SIGNATURE_INVALID``. - The specific officer is unknown or disabled. Returned with a code of ``TALER_EC_EXCHANGE_GENERIC_AML_OFFICER_ACCESS_DENIED``. + :http:statuscode:`500 Internal server error`: The server had an internal problem handling the request. The error code is usually a ``TALER_EC_GENERIC_DB_FETCH_FAILED``. diff --git a/core/exchange/get-aml-OFFICER_PUB-kyc-statistics-NAMES.rst b/core/exchange/get-aml-OFFICER_PUB-kyc-statistics-NAMES.rst @@ -37,17 +37,21 @@ All the event counters are zero. :http:statuscode:`400 Bad Request`: The request is malformed. Cases include: + - The ``$H_OFFICER_PUB`` path segment is malformed. This response comes with a standard `ErrorDetail` response with a code of ``TALER_EC_GENERIC_PATH_SEGMENT_MALFORMED``. - The required HTTP header with the signature is missing. Returned with ``TALER_EC_GENERIC_HTTP_HEADERS_MALFORMED``. + :http:statuscode:`403 Forbidden`: Two cases: + - The signature is invalid. Returned with a code of ``TALER_EC_EXCHANGE_GENERIC_AML_OFFICER_GET_SIGNATURE_INVALID``. - The specific officer is unknown or disabled. Returned with a code of ``TALER_EC_EXCHANGE_GENERIC_AML_OFFICER_ACCESS_DENIED``. + :http:statuscode:`414 URI Too Long`: The statistics names string in the URL is too long. This response comes with a standard `ErrorDetail` response with diff --git a/core/exchange/get-aml-OFFICER_PUB-legitimizations.rst b/core/exchange/get-aml-OFFICER_PUB-legitimizations.rst @@ -41,17 +41,21 @@ There are no matching legitimization measures. :http:statuscode:`400 Bad Request`: The request is malformed. Cases include: + - The ``$H_OFFICER_PUB`` path segment is malformed. This response comes with a standard `ErrorDetail` response with a code of ``TALER_EC_GENERIC_PATH_SEGMENT_MALFORMED``. - The required HTTP header with the signature is missing. Returned with ``TALER_EC_GENERIC_HTTP_HEADERS_MALFORMED``. + :http:statuscode:`403 Forbidden`: Two cases: + - The signature is invalid. Returned with a code of ``TALER_EC_EXCHANGE_GENERIC_AML_OFFICER_GET_SIGNATURE_INVALID``. - The specific officer is unknown or disabled. Returned with a code of ``TALER_EC_EXCHANGE_GENERIC_AML_OFFICER_ACCESS_DENIED``. + :http:statuscode:`500 Internal server error`: The server had an internal problem handling the request. The error code is usually a ``TALER_EC_GENERIC_DB_FETCH_FAILED``. diff --git a/core/exchange/get-aml-OFFICER_PUB-measures.rst b/core/exchange/get-aml-OFFICER_PUB-measures.rst @@ -23,17 +23,21 @@ `AvailableMeasureSummary` object. :http:statuscode:`400 Bad Request`: The request is malformed. Cases include: + - The ``$H_OFFICER_PUB`` path segment is malformed. This response comes with a standard `ErrorDetail` response with a code of ``TALER_EC_GENERIC_PATH_SEGMENT_MALFORMED``. - The required HTTP header with the signature is missing. Returned with ``TALER_EC_GENERIC_HTTP_HEADERS_MALFORMED``. + :http:statuscode:`403 Forbidden`: Two cases: + - The signature is invalid. Returned with a code of ``TALER_EC_EXCHANGE_GENERIC_AML_OFFICER_GET_SIGNATURE_INVALID``. - The specific officer is unknown or disabled. Returned with a code of ``TALER_EC_EXCHANGE_GENERIC_AML_OFFICER_ACCESS_DENIED``. + :http:statuscode:`500 Internal server error`: The server had an internal problem handling the request. The error code is usually a ``TALER_EC_GENERIC_DB_FETCH_FAILED``. diff --git a/core/exchange/get-deposits-H_WIRE-MERCHANT_PUB-H_CONTRACT_TERMS-COIN_PUB.rst b/core/exchange/get-deposits-H_WIRE-MERCHANT_PUB-H_CONTRACT_TERMS-COIN_PUB.rst @@ -30,7 +30,7 @@ executed. Hence the exchange does not yet have a wire transfer identifier. The merchant should come back later and ask again. The response body is a `TrackTransactionAcceptedResponse`. - :http:statuscode:`400 Bad request`: + :http:statuscode:`400 Bad Request`: A path parameter is malformed. This response comes with a standard `ErrorDetail` response. Possible error codes include @@ -42,7 +42,7 @@ The merchant signature is invalid. This response comes with a standard `ErrorDetail` response with a code of ``TALER_EC_EXCHANGE_DEPOSITS_GET_MERCHANT_SIGNATURE_INVALID``. - :http:statuscode:`404 Not found`: + :http:statuscode:`404 Not Found`: The deposit operation is unknown to the exchange. This response comes with a standard `ErrorDetail` response with a code of ``TALER_EC_EXCHANGE_DEPOSITS_GET_NOT_FOUND``. diff --git a/core/exchange/post-aml-OFFICER_PUB-decision.rst b/core/exchange/post-aml-OFFICER_PUB-decision.rst @@ -9,9 +9,9 @@ **Response** - :http:statuscode:`204 No content`: + :http:statuscode:`204 No Content`: The AML decision has been executed and recorded successfully. - :http:statuscode:`400 Bad request`: + :http:statuscode:`400 Bad Request`: The request was malformed. This response comes with a standard `ErrorDetail` response with a code of ``TALER_EC_GENERIC_PARAMETER_MALFORMED``. @@ -20,7 +20,7 @@ Returned with an error code of ``TALER_EC_EXCHANGE_AML_DECISION_ADD_SIGNATURE_INVALID`` or ``TALER_EC_EXCHANGE_GENERIC_AML_OFFICER_ACCESS_DENIED``. - :http:statuscode:`404 Not found`: + :http:statuscode:`404 Not Found`: The normalized payto-address the decision was made for is unknown to the exchange. Returned with an error code of: ``TALER_EC_EXCHANGE_GENERIC_BANK_ACCOUNT_UNKNOWN`` @@ -31,11 +31,11 @@ - ``TALER_EC_EXCHANGE_AML_DECISION_MORE_RECENT_PRESENT`` or - ``TALER_EC_EXCHANGE_AML_DECISION_INVALID_OFFICER`` - :http:statuscode:`413 Request entity too large`: + :http:statuscode:`413 Request Entity Too Large`: The uploaded body is to long, it exceeds the size limit. Returned with an error code of ``TALER_EC_GENERIC_UPLOAD_EXCEEDS_LIMIT``. - :http:statuscode:`500 Internal server error`: + :http:statuscode:`500 Internal Server Error`: The server had an internal error processing the request. Returned with one of various error codes, including: diff --git a/core/exchange/post-batch-deposit.rst b/core/exchange/post-batch-deposit.rst @@ -12,7 +12,7 @@ :http:statuscode:`200 OK`: The operation succeeded, the exchange confirms that no double-spending took - place. The response will include a `DepositSuccess` object. + place. The response will be a `DepositSuccessResponse` object. :http:statuscode:`400 Bad Request`: The request is malformed or a parameter is invalid. This response comes with a standard `ErrorDetail` response. diff --git a/core/exchange/post-coins-COIN_PUB-refund.rst b/core/exchange/post-coins-COIN_PUB-refund.rst @@ -10,50 +10,56 @@ :http:statuscode:`200 OK`: The operation succeeded, the exchange confirms that the coin can now be refreshed. The response will include a `RefundSuccess` object. - :http:statuscode:`400 Bad request`: + :http:statuscode:`400 Bad Request`: The request is somehow not following the protocol. Returned with error codes of: - ``TALER_EC_EXCHANGE_REFUND_FEE_TOO_LOW`` - ``TALER_EC_EXCHANGE_REFUND_FEE_ABOVE_AMOUNT`` + :http:statuscode:`403 Forbidden`: Merchant signature is invalid. This response comes with a standard `ErrorDetail` response. Returned with an error code of ``TALER_EC_EXCHANGE_REFUND_MERCHANT_SIGNATURE_INVALID``. - :http:statuscode:`404 Not found`: + :http:statuscode:`404 Not Found`: The refund operation failed as we could not find a matching deposit operation (coin, contract, transaction ID and merchant public key must all match). This response comes with a standard `ErrorDetail` response. - Returned with an error code of + Returned with an error code of: + - ``TALER_EC_EXCHANGE_REFUND_DEPOSIT_NOT_FOUND`` or - ``TALER_EC_EXCHANGE_REFUND_COIN_NOT_FOUND`` + :http:statuscode:`409 Conflict`: This response comes with a standard `ErrorDetail` response. There are several possible error codes: + - ``TALER_EC_EXCHANGE_REFUND_CONFLICT_DEPOSIT_INSUFFICIENT``: The requested amount for the refund exceeds the deposit value. - - - The exchange has previously received a refund request for the same coin, - merchant and contract, but specifying a different amount for the same - refund transaction ID. + - ``TALER_EC_EXCHANGE_REFUND_INCONSISTENT_AMOUNT``: + The exchange has previously received a refund request for the same + coin, merchant and contract, but specifying a different amount for + the same refund transaction ID. + :http:statuscode:`410 Gone`: It is too late for a refund by the exchange, the money was already sent to the merchant. This response comes with a standard `ErrorDetail` response. Returned with an error code of ``TALER_EC_EXCHANGE_REFUND_MERCHANT_ALREADY_PAID``. - :http:statuscode:`413 Request entity too large`: + :http:statuscode:`413 Request Entity Too Large`: The uploaded body is to long, it exceeds the size limit. Returned with an error code of ``TALER_EC_GENERIC_UPLOAD_EXCEEDS_LIMIT``. - :http:statuscode:`424 Failed dependency`: + :http:statuscode:`424 Failed Dependency`: The request transaction ID is identical to a previous refund request by the same merchant for the same coin and contract, but the refund amount differs. (The failed dependency is that the ``rtransaction_id`` is not unique.) Returned with an error code of: - ``TALER_EC_EXCHANGE_REFUND_INCONSISTENT_AMOUNT`` FIXME: consider turning this into a 409 in the future. - :http:statuscode:`500 Internal server error`: + :http:statuscode:`500 Internal Server Error`: The server encountered an internal error processing the request. Returned with error codes of: + - ``TALER_EC_EXCHANGE_REFUND_MERCHANT_SIGNING_FAILED`` - ``TALER_EC_GENERIC_DB_STORE_FAILED`` - ``TALER_EC_GENERIC_DB_FETCH_FAILED`` diff --git a/core/exchange/post-kyc-bulk-EXTERN_PUB.rst b/core/exchange/post-kyc-bulk-EXTERN_PUB.rst @@ -0,0 +1,106 @@ +.. http:post:: /kyc-bulk/$EXTERN_PUB + + The ``/kyc-import/$EXTERN_PUB`` POST endpoint allows third parties to + upload **large** KYC/KYB attachments. + The ``$EXTERN_PUB`` is the public EdDSA key + identifying the 3rd party encoded using Crockford base32 encoding. + + Clients should repeat this request (with some backoff) until it + succeeds. The request is idempotent, so repeating it is always safe. + The request may also be performed repeatedly for the same customer + data (payto:// and/or account public key) with the same or different + bulk data, for example to provide additional bulk data. + + See `KycBulkUploadAttribute` for how to reference bulk data + in KYC/KYB attributes. + + This endpoint was introduced in protocol **vIMPORT**. + + **Request:** + + The request body must be of one of the following file types: + + - application/pdf + - audio/ + - image/ + - video/ + - application/zip, containing PDF, audio/, image/ or + video/-files inside + + + The following HTTP headers must be provided: + + *Taler-Extern-Signature*: + $EXTERN_SIG`` where ``$EXTERN_SIG`` is the Crockford base32-encoded EdDSA + signature of purpose ``TALER_SIGNATURE_EXTERN_BULK_UPLOAD`` + and be made over the purpose header and the + SHA512 hash over the body and the SHA512 hash of the payto URI. + While the data will be timestamped server-side the client signature + does not include the timestamp. + See `ExternKycDataBulkBindingsPS <TALER_ExternKycDataBulkBindingPS>`_ for details. + + *Taler-Customer-Payto*: + payto:// URL of the bank account (or wallet) of the customer the bulk + data is about. + + *If-Not-Match*: + Crockford base32-encoded SHA-512 hash over the body to be uploaded. + Used by the server to prevent the upload if the data is already known. + + *Content-Length*: + Standard HTTP header with number of bytes in the body of the upload. + Required so that the server can perform sanity-checking early on. + + *Content-Type*: + Mime-type of the body. + Required so that the server can remember it for future use. + + + **Response:** + + :http:statuscode:`204 No Content`: + The information was successfully uploaded. + :http:statuscode:`400 Bad Request`: + The request body is malformed or a parameter is invalid. + This response comes with a standard `ErrorDetail` response with + a code of ``TALER_EC_GENERIC_PARAMETER_MALFORMED``. + The client should not repeat the request until its has been + restarted (presumably with a fixed implementation). + :http:statuscode:`403 Forbidden`: + The provided signature is invalid for the request. + This response comes with a standard `ErrorDetail` response with + a code of ``TALER_EC_KYC_BULK_SIGNATURE_INVALID``. + The client should not repeat the request until its has been + restarted (presumably with a fixed implementation). + :http:statuscode:`404 Not Found`: + The ``$EXTERN_PUB`` is unknown to the exchange. + This response comes with a standard `ErrorDetail` response. + Possible error codes include + ``TALER_EC_EXCHANGE_KYC_IMPORT_3RD_PARTY_UNKNOWN`` or + ``TALER_EC_GENERIC_ENDPOINT_UNKNOWN``. + The client should not repeat the request until its has been + restarted (presumably with a new configuration). + :http:statuscode:`411 Length required`: + The client must specify the ``Content-length`` header before + attempting upload. While technically optional by the + HTTP specification, the service may require + the client to provide the length upfront. + :http:statuscode:`412 Precondition failed`: + The information was already present server-side (If-Not-Match + condition failed). The client should not try again. + :http:statuscode:`413 Request Entity Too Large`: + The body is too large. This failure should be logged on both + ends. The request should not be repeated. If the uploaded + resource is a ZIP file with multiple files in it + the client MAY try to break up the upload into + multiple smaller POST requests. + :http:statuscode:`500 Internal Server Error`: + The server experienced an internal error. + This response comes with a standard `ErrorDetail` response. + Possible error codes include + ``TALER_EC_GENERIC_DB_STORE_FAILED``, + ``TALER_EC_GENERIC_DB_INVARIANT_FAILURE``, + ``TALER_EC_GENERIC_DB_SETUP_FAILED``, or + ``TALER_EC_EXCHANGE_KYC_GENERIC_AML_LOGIC_BUG``. + The request should be repeated with some exponential back-off, + giving the server operator to address its internal issues. diff --git a/core/exchange/post-kyc-import-EXTERN_PUB.rst b/core/exchange/post-kyc-import-EXTERN_PUB.rst @@ -0,0 +1,106 @@ +.. http:post:: /kyc-import/$EXTERN_PUB + + The ``/kyc-import/$EXTERN_PUB`` POST endpoint allows third parties to + upload KYC/KYB data. The ``$EXTERN_PUB`` is the public EdDSA key + identifying the 3rd party encoded using Crockford base32 encoding. + + Clients should repeat this request (with some backoff) until it + succeeds. The request is idempotent, so repeating it is always safe. + The request may also be performed repeatedly for the same customer + data (payto:// and/or account public key) with the same or different + attributes, for example to provide additional attributes or to + associate another account key pair with the same payto:// address. + The primary identify for any customer is always the payto:// address. + + .. note:: + + The exchange operator may internally notice that multiple payto:// + addresses actually refer to the same entity, but that is of no concern + for clients of this endpoint. + + Provided attributes may include data of type ``FileUpload``. In those + cases, the data may either be provided inline, or reference a previous + bulk import (by hash) performed via a POST to ``/kyc-bulk/``. + Bulk imports MUST always be performed before the import of attribute + data referencing the bulk data. + + This endpoint was introduced in protocol **vIMPORT**. + + **Request:** + + The request body must be a `KycDataImportRequest` object. + + **Response:** + + :http:statuscode:`204 No Content`: + The information was successfully uploaded. + :http:statuscode:`400 Bad Request`: + The request body is malformed or a parameter is invalid. + This response comes with a standard `ErrorDetail` response with + a code of ``TALER_EC_GENERIC_PARAMETER_MALFORMED``. + The client should not repeat the request until its has been + restarted (presumably with a fixed implementation). + :http:statuscode:`403 Forbidden`: + The provided signature is invalid for the request. + This response comes with a standard `ErrorDetail` response with + a code of ``TALER_EC_KYC_IMPORT_SIGNATURE_INVALID``. + The client should not repeat the request until its has been + restarted (presumably with a fixed implementation). + :http:statuscode:`404 Not Found`: + The ``$EXTERN_PUB`` is unknown to the exchange. + This response comes with a standard `ErrorDetail` response. + Possible error codes include + ``TALER_EC_EXCHANGE_KYC_IMPORT_3RD_PARTY_UNKNOWN`` or + ``TALER_EC_GENERIC_ENDPOINT_UNKNOWN``. + The client should not repeat the request until its has been + restarted (presumably with a new configuration). + :http:statuscode:`413 Request Entity Too Large`: + The body is too large. This failure should be logged on both + ends. The request should not be repeated. + :http:statuscode:`500 Internal Server Error`: + The server experienced an internal error. + This response comes with a standard `ErrorDetail` response. + Possible error codes include + ``TALER_EC_GENERIC_DB_STORE_FAILED``, + ``TALER_EC_GENERIC_DB_INVARIANT_FAILURE``, + ``TALER_EC_GENERIC_DB_SETUP_FAILED``, or + ``TALER_EC_EXCHANGE_KYC_GENERIC_AML_LOGIC_BUG``. + The request should be repeated with some exponential back-off, + giving the server operator to address its internal issues. + + **Details:** + + .. ts:def:: KycDataImportRequest + + interface KycDataImportRequest { + + // KYC attribute data. The fields present + // will depend on the 3rd party and the entity the data is about. + // Details will thus completely depend on the business context. + // However, it MUST include a form ID. + // Furthermore, the exchange may impose specific + // restrictions on importing KYC data based on the 3rd party + // and the respective business agreement. + attributes: CustomerKycAttributes; + + // Time when the attributes were obtained by the 3rd party. + import_date: Timestamp; + + // payto-URI of the bank account (or theoretically wallet) + // for which the KYC/KYB data was obtained. + customer_payto: string; + + // Public key of the merchant backend instance (or wallet) + // that should be associated with the KYC/KYB data. + account_pub: EddsaPublicKey; + + // EdDSA signature of the 3rd party. Must be of + // purpose ``TALER_SIGNATURE_EXTERN_KYC_IMPORT_BINDING`` + // and be made over the purpose header and the + // SHA512 hash over the (normalized) JSON of ``attributes`` + // as well as the timestamp, SHA512 hash of the payto URI + // and the merchant public key. + // See `TALER_ExternKycDataImportBindingPS` for details. + extern_sig: EddsaSignature; + + } diff --git a/core/exchange/post-reveal-melt.rst b/core/exchange/post-reveal-melt.rst @@ -48,7 +48,7 @@ - ``TALER_EC_GENERIC_INTERNAL_INVARIANT_FAILURE`` - ``TALER_EC_GENERIC_DB_STORE_FAILED`` - ``TALER_EC_GENERIC_DB_FETCH_FAILED`` - :http:statuscode:`503 Service unvailable`: + :http:statuscode:`503 Service Unavailable`: Returned with an error code of ``TALER_EC_EXCHANGE_GENERIC_KEYS_MISSING``. diff --git a/core/exchange/post-reveal-withdraw.rst b/core/exchange/post-reveal-withdraw.rst @@ -16,10 +16,12 @@ :http:statuscode:`200 OK`: The coin's' secret material matched the commitment and the original request was well-formed. The response body is a `RevealResponse`. - :http:statuscode:`400 Bad request:` + :http:statuscode:`400 Bad Request`: The request from the client is malformed. Error codes used are: + - ``TALER_EC_GENERIC_PARAMETER_MALFORMED`` - ``TALER_EC_EXCHANGE_WITHDRAW_REVEAL_INVALID_HASH`` + :http:statuscode:`404 Not found`: The provided commitment $RCH is unknown. Error code: ``TALER_EC_EXCHANGE_WITHDRAW_COMMITMENT_UNKNOWN`` @@ -30,8 +32,10 @@ :http:statuscode:`500 Internal Server Error`: Returned if the server had an internal issue processing the request. Error codes include: + - ``TALER_EC_GENERIC_DB_FETCH_FAILED`` - ``TALER_EC_GENERIC_INTERNAL_INVARIANT_FAILURE`` + :http:statuscode:`503 Service unavailable`: The server could not process the request because it is currently unavailable. Error codes include: diff --git a/core/merchant/get-private-incoming-ID.rst b/core/merchant/get-private-incoming-ID.rst @@ -2,7 +2,7 @@ Obtain details about an expected incoming wire transfers the backend is anticipating. ID must be the ``expected_transfer_serial_id`` - from `ExpectedTransferDetails`. + from `ExpectedTransferEntry`. Since protocol **v26**. **Required permission:** ``transfers-read`` diff --git a/core/merchant/post-instances.rst b/core/merchant/post-instances.rst @@ -9,7 +9,7 @@ **Request:** - The request must be a `InstanceConfigurationMessage`. + The request must be a `InstanceConfigurationRequest`. :query token_validity_ms=DURATION: *Optional*. Pass a non-zero DURATION in milliseconds to get a diff --git a/deployments/tops.rst b/deployments/tops.rst @@ -594,12 +594,10 @@ include the fields FORM_ID and FORM_VERSION attributed as defined in GANA. Field names are always in ``SCREAMING_SNAKE_CASE``. -File uploads should always use a single field named ``FILE`` with the following nested attributes: +File uploads should always use a nested structure, either +using ``FILE`` with a `KycFileUploadAttribute` or +``BULK`` with a `KycBulkUploadAttribute`. -* ``CONTENTS``: Encoded contents as a string, encoding determined by ``ENCODING`` -* ``ENCODING``: Encoding of contents, currently only ``base64`` is supported. -* ``FILENAME``: *Optional*. File name of the upload. -* ``MIME_TYPE``: MIME type of the uploaded file. accept-tos ^^^^^^^^^^ diff --git a/design-documents/073-extended-merchant-template.rst b/design-documents/073-extended-merchant-template.rst @@ -276,7 +276,7 @@ per-product logic when available. } Next structure mirrors the merchant product descriptor (``ProductDetail`` in the -merchant specification) with some extensions (unit_name_short_i18n, ) so that backend, SPA, and wallet +merchant specification) with some extensions (unit_name_short_i18n, ) so that backend, SPA, and wallet share a single meaning for every field, yet we lower the number of requests between the wallet and backend. @@ -320,40 +320,7 @@ Template instantiation ---------------------- Extend ``POST /instances/$INSTANCE/templates/$TEMPLATE_ID`` to support the -following sum type: - -.. ts:def:: UsingTemplateDetailsType - - type UsingTemplateDetailsType = - UsingTemplateDetails | InventoryTemplateUseDetails - - -.. ts:def:: InventoryTemplateUseDetails - - interface InventoryTemplateUseDetails { - - // Summary of the template. - summary?: string; - - // Amount pre-calculated on the wallet side. - // Do we want to allow null? (e.g. wallet is lazy) - amount: Amount; - - // Optional tip selected by the customer and mapped to - // an abstract line item in the resulting order. - tip?: Amount; - - // Selected products. When choose_one = true the array must contain - // exactly one entry. - inventory_selection: InventoryTemplateSelection[]; - } - -.. ts:def:: InventoryTemplateSelection - - interface InventoryTemplateSelection { - product_id: string; - quantity: string; - } +`UsingTemplateCommonRequest` type. ``amount`` lets the wallet supply a precalculated total; backends recompute the authoritative order amount and reject mismatches. diff --git a/design-documents/078-taxes.rst b/design-documents/078-taxes.rst @@ -142,7 +142,8 @@ given product or order. (8) rounding mode (up, down, nearest) (9) rounding unit (amount) (10) money pot (where to accumulate taxes paid under this tax class). - to track known tax rules. Unique should be "instance+tax class name". + to track known tax rules. + Unique should be "instance+tax class name". * When "rounding up" is used, round up from net to gross, but round down from gross to net. Similarly, when "rounding down" is used, diff --git a/design-documents/086-wallet-design.rst b/design-documents/086-wallet-design.rst @@ -31,8 +31,8 @@ Empty Wallet .. image:: wallet-designs/empty-wallet-webex.png On top of the screen is logo: - - Logo for light mode `here <wallet-designs/taler-logo-light.png>`_ - - Logo for dark mode `here <wallet-designs/taler-logo-dark.png>`_ + - Logo for `light mode <wallet-designs/taler-logo-light.png>`_ + - Logo for `dark mode <wallet-designs/taler-logo-dark.png>`_ Withdrawal of real cash and demo cash is separated for two cards. diff --git a/design-documents/087-wallet-onboarding.rst b/design-documents/087-wallet-onboarding.rst @@ -28,8 +28,10 @@ This is the screen user will see when they open the wallet for the first time, b .. image:: wallet-designs/empty-wallet-webex.png On top of the screen is logo: - - Logo for light mode `link to png file <wallet-designs/taler-logo-light.png>`_, `link to svg file <wallet-designs/taler-logo-light.svg>`_ - - Logo for dark mode `link to png file <wallet-designs/taler-logo-dark.png>`_, `link to svg file <wallet-designs/taler-logo-dark.svg>`_ + - Logo for: `light mode png file <wallet-designs/taler-logo-light.png>`_, + `light mode svg file <wallet-designs/taler-logo-light.svg>`_ + - Logo for: `dark mode png file <wallet-designs/taler-logo-dark.png>`_, + `dark mode svg file <wallet-designs/taler-logo-dark.svg>`_ Withdrawal of real cash and demo cash is separated for two cards. diff --git a/libeufin/nexus-manual.rst b/libeufin/nexus-manual.rst @@ -28,10 +28,10 @@ Nexus Manual LibEuFin Nexus is an EBICS facilitator. It offers a command line interface to setup EBICS access, download banking records, and submit payments. LibEuFin Nexus is not a generic EBICS client but a Taler specific one. -Today, the LibEuFin implementation supports EBICS 3.0 and has been -tested with Postfinance (CHF), GLS (EUR), Raiffeisen (CHF), Maerki Baumann (CHF) and Valiant (CHF). Please note -that banks tend to have their own dialects of finance messages and thus other -retail banks may or may not work. Contact us if you need support for another +Today, the LibEuFin implementation supports EBICS 3.0 and has been +tested with Postfinance (CHF), GLS (EUR), Raiffeisen (CHF), Maerki Baumann (CHF) and Valiant (CHF). Please note +that banks tend to have their own dialects of finance messages and thus other +retail banks may or may not work. Contact us if you need support for another bank or core banking protocol. In this manual, we explain how to setup an EBICS subscriber. We assume that @@ -124,7 +124,7 @@ submitted to the database, so this section only discusses how such queued payments will be executed. The responsible subcommand for sending payments is ``ebics-submit``, and its -configuration is a **superset** of :ref:`nexus-core-config`. On top of that, it expects +configuration is a **superset** of `nexus-core-config <nexus-core-config>`_. On top of that, it expects the database connection string and *optionally* a frequency at which it will check for submittable payments in the database. @@ -210,27 +210,27 @@ Downloading payments must follow a successful `EBICS subscriber setup subscriber accepted the bank keys. Furthermore, the database has to be set up. -The responsible subcommand for fetching and registering payments is -``ebics-fetch``, and its configuration is a **superset** of nexus-core-config_. On -top of that, it expects the database connection string and *optionally* a +The responsible subcommand for fetching and registering payments is +``ebics-fetch``, and its configuration is a **superset** of nexus-core-config_. On +top of that, it expects the database connection string and *optionally* a frequency and a checkpoint time of day. -For the best user experience, new transactions should be registered as soon as -they are booked. This is especially important for instant transactions, which -reach final status in ~10 seconds. On the other hand, EBICS document fetches +For the best user experience, new transactions should be registered as soon as +they are booked. This is especially important for instant transactions, which +reach final status in ~10 seconds. On the other hand, EBICS document fetches are slow and expensive and should not be performed more than necessary. -``ebics-fetch`` will run a periodical fetch of pending documents (documents -that have never been fetched before). If the bank server supports it, it will -also listen to real-time document availability notifications and fetch -documents as soon as they are announced. This enables instant registration of -instant transactions. If your bank server does not support real-time -notifications, it is recommended that you fetch more often; otherwise, you can +``ebics-fetch`` will run a periodical fetch of pending documents (documents +that have never been fetched before). If the bank server supports it, it will +also listen to real-time document availability notifications and fetch +documents as soon as they are announced. This enables instant registration of +instant transactions. If your bank server does not support real-time +notifications, it is recommended that you fetch more often; otherwise, you can reduce the fetch frequency. -Only fetching pending documents is not always reliable, if other EBICS clients -use the same connection settings as ``libeufin-nexus``, they can consume documents before they are ingested. In case of bank downtime, the status of -documents can be lost. This is why ``ebics-fetch`` will run a checkpoint every +Only fetching pending documents is not always reliable, if other EBICS clients +use the same connection settings as ``libeufin-nexus``, they can consume documents before they are ingested. In case of bank downtime, the status of +documents can be lost. This is why ``ebics-fetch`` will run a checkpoint every day to download all documents generated since the last checkpoint. If the bank supports real-time notifications, you can expect transactions to be registered as soon as they are booked: ~10s for instant transactions and 24 to 72h for other transactions. Otherwise, expect a latency corresponding to the fetch frequency for instant transactions. Thanks to checkpointing, latency should not exceed one day. @@ -251,7 +251,7 @@ The checkpoint time of day **may** be specified as [nexus-fetch] CHECKPOINT_TIME_OF_DAY = 19:00 -Assuming that ``$CONFIG_FILE`` contains all required options, the following +Assuming that ``$CONFIG_FILE`` contains all required options, the following command would download any unseen EBICS files: .. code-block:: console @@ -262,7 +262,7 @@ The ``ebics-fetch`` subcommand will always cause libeufin-nexus to download then parse EBICS files and register their content statements into its local database. -The ``--transient`` flag makes the command download and import EBICS files only +The ``--transient`` flag makes the command download and import EBICS files only once and return immediately afterwards. Without the flag, Nexus will download at the frequency specified in the configuration or when it receive real time notifications. @@ -319,12 +319,12 @@ the present: Manual balance adjustement ========================== -As LibEuFin Nexus is a Taler-specific EBICS client, it ignores non-payment -transactions. This means that certain debits from your banks for fees or taxes +As LibEuFin Nexus is a Taler-specific EBICS client, it ignores non-payment +transactions. This means that certain debits from your banks for fees or taxes can be ignored. This imply that the actual balance of your bank account may deviate from that expected by Taler Exchange, leading to Exchange bankruptcy. -To fix this, you must periodically send administrative balance adjustment -transfers conaining "ADMIN BALANCE ADJUST" in their subject. +To fix this, you must periodically send administrative balance adjustment +transfers conaining "ADMIN BALANCE ADJUST" in their subject. Manual submission acknowledgement ================================= diff --git a/taler-kyc-manual.rst b/taler-kyc-manual.rst @@ -743,7 +743,7 @@ administrator. // the keys in the JSON object will be the attribute // names and the values must be strings representing // the data. In the case of file uploads, the data - // MUST be base64-encoded. + // MUST be base64-encoded or be an external upload. // Attributes are only provided if the AML program // specifies "attributes" for its input requirements. attributes?: Object;