taler-docs

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

commit 864be019f75faad33b76c534459498c5eede7b83
parent 38df5382734bcf4de85c0f65e27a1b8800594ad9
Author: Christian Grothoff <christian@grothoff.org>
Date:   Sat,  9 May 2020 17:50:39 +0200

Merge branch 'master' of git+ssh://git.taler.net/docs

Diffstat:
Mcore/api-merchant.rst | 2+-
Mdesign-documents/004-wallet-withdrawal-flow.rst | 6++++++
Mdevelopers-manual.rst | 36++++++++++++++++++++++++++++++++----
Alibeufin/api-nexus2.rst | 300+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Dlibeufin/architecture.rst | 58----------------------------------------------------------
Mlibeufin/concepts.rst | 29+++++++++++++++--------------
Mlibeufin/index.rst | 3+--
Mtaler-merchant-api-tutorial.rst | 1+
Mtaler-wallet.rst | 61+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--
9 files changed, 415 insertions(+), 81 deletions(-)

diff --git a/core/api-merchant.rst b/core/api-merchant.rst @@ -938,7 +938,7 @@ Receiving Payments exchange_url: string; } - +.. _order-abort: .. http:post:: /orders/$ORDER_ID/abort Abort paying for an order and obtain a refund for coins that diff --git a/design-documents/004-wallet-withdrawal-flow.rst b/design-documents/004-wallet-withdrawal-flow.rst @@ -107,6 +107,12 @@ the user is brought to the list of transactions of the current currency. It will include a pending `TransactionWithdrawal` which might require additional user confirmation such as a two-factor-authentication step with the bank. +1. The bank transfer happens immediately +2. A second factor is required which is "detached", + i.e. you have to press "confirm" on a physical Taler ATM, + or a Taler cashier has to do a final "confirm" on their device. +3. The bank provides a ``bankConfirmationUrl`` that the user needs to visit. + If the withdrawal proceeds very quickly, the `TransactionWithdrawal` might not show as pending and its effective amount is added to the displayed balance right away. diff --git a/developers-manual.rst b/developers-manual.rst @@ -621,6 +621,33 @@ Upgrading Privileges To upgrade from **Users**/**Viewers**, a superuser must manually augment your privileges. At this time, superusers are Christian, Florian, and Buck. +How to Create a Project +----------------------- + +The *GNU Taler* project is probably the correct project for most Components and Translations falling under this guide. Please contact a superuser if you need another Project created. + +How to Create a Component +------------------------- + +Reference: https://docs.weblate.org/en/weblate-4.0.3/admin/projects.html#component-configuration + +In Weblate, a *Component* is a subset of a *Project* and each Component contains N translations. A Component is generally associated with a Git repo. + +To create a Component, log into https://weblate.taler.net/ with your *Manager* or higher credentials and choose **+ Add* from the upper-right corner. + +What follows is a sort of Wizard. You can find detailed docs at https://docs.weblate.org/. Here are some important notes about connecting your Component to the Taler Git repository: + +Under *https://weblate.taler.net/create/component/vcs/*: + +* **Source code repository** - Generally `git+ssh://git@git.taler.net/<reponame>`. Check with `git remote -v`. +* **Repository branch** - Choose the correct branch to draw from and commit to. +* **Repository push URL** - This is generally `git+ssh://git@git.taler.net/<reponame>` Check with `git remote -v`. +* **Repository browser** - This is the www URL of the Git repo's file browser. Example `https://git.taler.net/<repositoryname>.git/tree/{{filename}}?h={{branch}}#n{{line}}` where <repositoryname> gets replaced but *{{filename}}* and other items in braces are actual variables in the string. +* **Merge style** - *Rebase*, in line with GNU Taler development procedures + +* **Translation license** - *GNU General Public License v3.0 or Later* +* **Adding new translation** - Decide how to handle adding new translations + How to Create a Translation --------------------------- @@ -628,9 +655,9 @@ How to Create a Translation 2 - Navigate to *Projects* > *Browse all projects* -3 - Choose the *project* you wish to contribute to. +3 - Choose the *Project* you wish to contribute to. -4 - Choose the *component* you wish to contribute to. +4 - Choose the *Component* you wish to contribute to. 5 - Find the language you want to translate into. Click "Translate" on that line. @@ -641,10 +668,11 @@ You may also wish to refer to ``https://docs.weblate.org/``. Translation Standards and Practices ----------------------------------- -By default, our Weblate instance is set to accept translations in English, French, German, Italian, Russian, Spanish, and Portuguese. +By default, our Weblate instance is set to accept translations in English, French, German, Italian, Russian, Spanish, and Portuguese. If you want to contribute a translation in a different language, navigate to the *Component* you want to translate for, and click "Start new translation" to begin. If you require a privilege upgrade, please contact a superuser with your request. -If you want to contribute a translation in a different language, navigate to the *Component* you want to translate for, and click "Start new translation" to begin. If you require a privilege upgrade, please contact a superuser with your request. +When asked, set the license to GPLv3 or later. +Set commit/push to manual only. GPG Signing of Translations --------------------------- diff --git a/libeufin/api-nexus2.rst b/libeufin/api-nexus2.rst @@ -0,0 +1,300 @@ +Nexus API +########### + +HTTP API +======== + +Authentication +-------------- + +Currently every request made to nexus must be authenticated using the *HTTP +basic auth* mechanism. + +Other authentication mechanisms (e.g. OpenID Connect) might +be supported in the future. + +Users Management +---------------- + +.. http:get:: <nexus>/user + + Get information about the current user (based on the authentication information + in this request). + + **Response:** + + .. ts:def:: GetUserResponse + + interface UserResponse { + + // User name + username: string; + + // Is it a superuser? + superuser: boolean; + } + +.. http:post:: <nexus>/users + + Create a new user. Only the super-user can call this API. + + **Request:** + + The body is a `User` object. + + **Response:** + + :status 409 Conflict: Username is not available. + + **Details:** + + .. ts:def:: CreateUserRequest + + interface User { + + // User name + username: string; + + // Initial password + password: string; + } + +Bank Account Management +----------------------- + +.. http:get:: <nexus>/bank-accounts + + **Response:** + + A list of `BankAccount` objects + that belong to the requester. + + .. ts:def:: BankAccount + + interface BankAccount { + // mnemonic name identifying this bank account. + account: string; + // IBAN + iban: string; + // BIC + bic: string; + // Legal subject owning the account. + holder: string; + } + +.. http:post:: <nexus>/bank-accounts/<my-acct>/prepared-payments/submit + + Ask nexus to submit one prepare payment at the bank. + + **Request:** + + .. ts:def:: SubmitPayment + + interface SubmitPayment { + // Unique identifier of the (previously) prepared payment + // to submit at the bank. + uuid: string; + + // Optional field to specify the bank transport to use + // for the submission. + transport: string; + } + + :status 404 Not Found: the unique identifier **or** + the bank transport could not be found in the system + + +.. http:get:: <nexus>/bank-accounts/<my-acct>/prepared-payments/$uuid + + Ask the status of payment ``$uuid``. + + **Response:** + + .. ts:def:: PaymentStatus + + interface PaymentStatus { + + // Payment unique identifier + uuid: string; + + // True for submitted payments + submitted: boolean; + + // Creditor IBAN + creditorIban: string; + + // Creditor BIC + creditorBic: string; + + // Creditor legal name + creditorName: string; + + // Amount + amount: string; + + // Date of submission (in dashed form YYYY-MM-DD) + submissionDate: string; + + // Date of preparation (in dashed form YYYY-MM-DD) + preparationDate: string; + } + +.. http:post:: <nexus>/bank-accounts/<my-acct>/prepared-payments + + Ask nexus to prepare instructions for a new payment. + Note that ``my-acct`` is the bank account that will be + **debited** after this operation. + + **Request:** + + .. ts:def:: PreparedPaymentRequest + + interface PreparedPayment { + // IBAN that will receive the payment. + iban: string; + // BIC hosting the IBAN. + bic: string; + // Legal subject that will receive the payment. + name: string; + + // amount, in the format CURRENCY:XX.YY + amount: string + } + + **Response:** + + .. ts:def:: PreparedPaymentResponse + + interface PreparedPaymentResponse { + + // Opaque identifier to be communicated when + // the user wants to submit the payment to the + // bank. + uuid: string; + } + +.. http:post:: <nexus>/bank-accounts/<my-acct>/collected-transactions + + Ask the default transport to download the latest transactions + related to ``my-acct`` and store them locally. + + **Request:** + + .. ts:def:: CollectTransactions + + interface CollectTransactions { + // Optional field to specify the bank transport to + // use for such operation. + bankTransport?: string; + // dashed date (YYYY-MM-DD) of the earliest payment + // in the result. Optional, defaults to "earliest + // possible" date. + start: string; + // dashed date (YYYY-MM-DD) of the earliest payment + // in the result. Optional, defaults to "latest + // possible" date. + end: string; + } + +.. http:get:: <nexus>/bank-accounts/<my-acct>/collected-transactions + + Shows which transactions are stored locally at nexus. + + **Query parameters:** + + * **start** start (dashed YYYY-MM-DD) date of desired payments. + Optional, defaults to "earliest possible" date + * **end** end (dashed YYYY-MM-DD) date of desired payments. + Optional, defaults to "earliest possible" date + + + **Response:** A list of `Transaction` objects. + + .. ts:def:: Transaction + + interface Transaction { + // local bank account involved in the transaction. + account: string; + + // counterpart IBAN + counterpartIban: string; + + // counterpart BIC + counterpartBic: string; + + // counterpart holder name + counterpartName: string; + + // amount, in the format [-]CURRENCY:XX.YY, + // where the minus sign as prefix indicates + // a debit for the user's bank account. + amount: string + } + +Bank Transports +--------------- + +Bank transports connect the local LibEuFin bank account +to the real bank. + +.. http:post:: <nexus>/bank-transports + + Activate a new bank transport for the requesting user. + + **Request:** + Object of the type `BankTransport` + + **Response:** + + :status 409 Conflict: The ``name`` field exists already for + the requesting user. + + **Details:** + + .. ts:def:: BankTransport + + interface BankTransport { + + // Mnemonic identifier for the transport bein created. + name: string; + + // Optional field to restore a previous transport. + backup: TransportBackup; + + // Type of the transport (ebics, fints, native, ..) + type: string; + } + + + .. ts:def:: TransportBackup + + interface TransportBackup { + + // The information needed in this type depend entirely + // on which transport is being restored. + + } + +.. http:post:: <nexus>/bank-transports/<transport-name>/sendMSG. + + Perform the ``MSG`` operation offered by ``transport-name`` + **without** affecting the nexus database. + + **Response:** + + :status 404 Not Found: ``transport-name`` doesn't exist for + the requesting user. + +.. http:post:: <nexus>/bank-transports/<transport-name>/syncMSG. + + Some transports **do** have operations that aren't semantically + related to a bank account but need to be stored locally at the nexus. + One typical example is the downloading of the bank's keys vie the + EBICS transport. This API lets the user perform the ``MSG`` + operation that should result in new data being stored locally + at the nexus. + + **Response:** + + :status 404 Not Found: ``transport-name`` doesn't exist for + the requesting user. diff --git a/libeufin/architecture.rst b/libeufin/architecture.rst @@ -1,58 +0,0 @@ -LibEuFin Architecture -##################### - -Sandbox -======= - -* the sandbox's EBICS API emulates the behavior of a real bank's EBICS - interface - -* *(Only in the future)*: FinTS API and other FinTech APIs - -* the sandbox's management API allows an administrator to: - - * create new **bank** accounts - * create new **EBICS subscriber** accounts - - * a subscriber has (optionally?) a SystemID (for technical subscribers), - a UserID and a PartnerID - * each bank account has a list of subscribers than can access it - - * delete accounts - * ... - -* the sandbox's "miscellaneous" API provides public functionality that is not covered - directly by EBICS, such as: - - * a way to get the transactions in form of a JSON message, to check if it matches the EBICS response - - * you could call it a "reference history" - - * publicly accessible key management functionality, for example for the EBICS INI process - - * this is the "electronic version" of sending an HIA/INI letter - -* things that we do **not** want to implement right now: - - * Distributed electronic signatures. For now, it is enough for every order - to be signed just by one authorized subscriber. - -Nexus -===== - -The Nexus takes JSON requests and translates them into API calls for the -respective real bank accounts (EBICS, FinTS, ...). It also stores the bank -transaction history to enable a linearlized view on the transaction history -with unique transaction identifier, which some of the underlying banking APIs -don't provide directly. - -``libeufin-nexus-httpd`` is the binary (or wrapper around the Java invocation) -that runs the HTTP service. - - -CLI Tools -========= - -The Sandbox and Nexus are only HTTP services. The CLI tools are used to -actually access them. - diff --git a/libeufin/concepts.rst b/libeufin/concepts.rst @@ -85,7 +85,7 @@ Bank transports provide the following actions: * Execute protocol-specific actions (e.g. EBICS: C53, C52, CCT, CRZ) - * These actions to not have any effect on the LibEuFin local bank account. + * These actions do not have any effect on the LibEuFin local bank account. To persist changes to the local bank account (transaction history, payment request status), the bank transport must be invoked via the bank account. @@ -104,20 +104,21 @@ Examples: # Download available bank accounts that can be accessed through this transport, # according to the bank server (with EBICS, does a HTD request). - curl -XPOST $AUTHEADER https://example1.libeufin.tech/bank-transports/my-ebics-testacct/query-bank-accounts + # For each of them, create a bank account resource in LibEuFin. + curl -XPOST $AUTHEADER https://example1.libeufin.tech/bank-transports/my-ebics-testacct/import-accounts -Layers ------- +Facades +------- -Layers allow extra domain-specific functionality to be implemented on top of users, bank accounts -and bank transports. Layers store the following information: +Facades allow extra domain-specific functionality to be implemented on top of users, bank accounts +and bank transports. Facades store the following information: -* Local name of the layer -* Layer type and options specific to the type -* associated bank accounts and bank transports that can be accessed by the layer -* internal tables used by the layer (i.e. layers are stateful) +* Local name of the facade +* Facade type and options specific to the type +* Associated bank accounts and bank transports that can be accessed by the layer +* Internal tables used by the facade (i.e. facades are stateful) -The only layer currently supported by LibEuFin is the "Taler Wire Gateway API" layer. +The only facade currently supported by LibEuFin is the "Taler Wire Gateway API" layer. It provides a filtered view on the transaction history, a more restricted API to create payment requests, and a mechanism to create a counter-transaction for incoming transaction that do not conform to a certain format. @@ -126,8 +127,8 @@ Examples: .. code:: none - # Request the Taler-specific history through the layer - curl $AUTHEADER https://example1.libeufin.tech/layers/my-taler-wire-gw/api/history/incoming + # Request the Taler-specific history through the facade + curl $AUTHEADER https://example1.libeufin.tech/facades/my-taler-wire-gw/api/history/incoming Access Control ============== @@ -149,7 +150,7 @@ Each top-level object (bank account, bank transport, layer) has a list of nexus users with write access, and a list of users with read access. When using a bank transport through a bank account, permission checks must -succees for both the bank account and the bank transport. +succeed for both the bank account and the bank transport. This works differently for layers: A layer has a set of associated bank transports and bank accounts it can access. Permissions on these associated objects diff --git a/libeufin/index.rst b/libeufin/index.rst @@ -8,7 +8,6 @@ LibEuFin is a project providing free software tooling for European FinTech. concepts ebics - architecture api-sandbox - api-nexus + api-nexus2 iso20022 diff --git a/taler-merchant-api-tutorial.rst b/taler-merchant-api-tutorial.rst @@ -279,6 +279,7 @@ This code snipped illustrates giving a refund: .. index:: repurchase +.. _repurchase: Repurchase detection and fulfillment URLs ========================================= diff --git a/taler-wallet.rst b/taler-wallet.rst @@ -102,7 +102,10 @@ Transactions are all operations or events that are affecting the balance. .. ts:def:: TransactionsResponse interface TransactionsResponse { - // a list of past and pending transactions + // a list of past and pending transactions sorted by pending, timestamp and transactionId. + // In case two events are both pending and have the same timestamp, + // they are sorted by the transactionId + // (lexically ascending and locale-independent comparison). transactions: Transaction[]; } @@ -120,6 +123,8 @@ Transactions are all operations or events that are affecting the balance. timestamp: Timestamp; // true if the transaction is still pending, false otherwise + // If a transaction is not longer pending, its timestamp will be updated, + // but its transactionId will remain unchanged pending: boolean; // Raw amount of the transaction (exclusive of fees or other extra costs) @@ -288,8 +293,11 @@ Refunds } +Integration Tests +================= + Integration Test Example -======================== +------------------------ Integration tests can be done with the low-level wallet commands. To select which coins and denominations to use, the wallet can dump the coins in an easy-to-process format (`CoinDumpJson <https://git.taler.net/wallet-core.git/tree/src/types/talerTypes.ts#n734>`__). @@ -351,3 +359,52 @@ top-level command and not the subcommand: # Update exchange /keys with time travel, value in microseconds $ taler-wallet-cli --timetravel=1000000 --wallet-db=mydb.json exchanges update -f https://exchange.int.taler.net/ +Test Cases +---------- + +Things we already have tests for: + +* Can the wallet recoup coins and spend them? + [`link <https://git.taler.net/wallet-core.git/tree/integrationtests/test-recoup.sh>`__] + +Things we still need tests for: + +* Does the wallet do retries correctly when the exchange is not reachable? + Or when the merchant is not reachable? Or the bank? + This can be tested by temporarily killing those services. +* How does the wallet deal with processing the same ``taler://(pay|withdraw)`` URI twice? +* Test tipping (accepting/refusing a tip) +* Test refunds +* Test for :ref:`session-based payments <repurchase>` +* Test case for auto-refunds + (scenario where the vending machine finds out that its motor is broken, + so it automatically gives a refund) +* Does the wallet report "insufficient balance" correctly + (as opposed to, say, crashing)? +* Perf tests: How does the wallet handle withdrawing a *LOT* of coins? +* Are the transaction history and pending operations reported correctly? + +Tests for things the wallet doesn't handle correctly yet: + +* What happens if the wallet double-spends a coin? + (Easy to test by copying the wallet DB before spending + and then running a spend again with the old DB). +* What happens when a reserve is changed between accepting withdrawal + and actually withdrawing coins? + (This is harder to test. Might not be possible with the current CLI. + The idea would be be to have some ``--inhibit=withdraw`` flag + that tells the wallet to not actually withdraw, + so we can change the reserve state and then resume the wallet.) +* What happens if the exchange suddenly has a completely new list of denominations on offer? +* What happens if the exchange changes its master public key? + The wallet *should* handle this gracefully + even if we have coins with that exchange, + provided that the old denominations can be recouped. + (That one is pretty difficult!) +* Does the wallet handle :ref:`payment aborts <order-abort>` correctly? + +There are test cases that require us to modify the communication between the wallet and exchange. + +* What does the wallet do when the exchange/merchant announce an incompatible protocol version? +* What happens if some signature made by the exchange/merchant is garbage? +* What if the exchange reports a double-spend and the proof it gives us is invalid?