taler-docs

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

commit ee1e172c77c40b15e2cb77011d1a8daefe860ea9
parent a7a359dd44d0008c7cce6ef88c853f7ffa99c141
Author: Florian Dold <dold@taler.net>
Date:   Fri, 21 Aug 2026 00:31:47 +0200

design documents: record lifecycle and implementation status

Diffstat:
Mcore/api-bank-integration.rst | 8++++----
Mcore/api-mailbox.rst | 5+++--
Mcore/api-merchant.rst | 38+++++++++++++++++++++++++++++++++++++-
Mcore/api-taldir.rst | 3++-
Mcore/bank-transfer/post-registration.rst | 2+-
Mcore/exchange/get-keys.rst | 9---------
Mcore/exchange/post-batch-deposit.rst | 144-------------------------------------------------------------------------------
Mcore/exchange/post-coins-COIN_PUB-refund.rst | 5+++++
Mcore/exchange/post-reveal-melt.rst | 4++--
Mcore/mailbox/get-H_MAILBOX.rst | 3++-
Mcore/mailbox/get-info-H_MAILBOX.rst | 3++-
Mcore/merchant/get-private-statistics-amount-SLUG.rst | 2+-
Mcore/merchant/get-private-statistics-counter-SLUG.rst | 2+-
Mcore/merchant/get-private-statistics-report-NAME.rst | 18+++++++++++-------
Mdesign-documents/001-new-browser-integration.rst | 10++++++++++
Mdesign-documents/002-wallet-exchange-management.rst | 12++++++++++++
Mdesign-documents/003-tos-rendering.rst | 13+++++++++++--
Mdesign-documents/004-wallet-withdrawal-flow.rst | 12+++++++++++-
Mdesign-documents/005-wallet-backup-sync.rst | 14++++++++++++--
Mdesign-documents/006-extensions.rst | 9+++++++++
Mdesign-documents/007-payment.rst | 17++++++++++++++++-
Mdesign-documents/008-fees.rst | 10++++++++++
Mdesign-documents/009-backup.rst | 10++++++++++
Mdesign-documents/010-exchange-helpers.rst | 39+++++++++++++++++++++++----------------
Mdesign-documents/011-auditor-db-sync.rst | 15+++++++++++++++
Mdesign-documents/012-fee-schedule-metrics.rst | 22+++++++++++++++++-----
Mdesign-documents/013-peer-to-peer-payments.rst | 73++++++++++++++++++++++++++++++++++++++++++++-----------------------------
Mdesign-documents/014-merchant-backoffice-ui.rst | 32++++++++++++++++++++++----------
Mdesign-documents/015-merchant-backoffice-routing.rst | 30++++++++++++++++++++++--------
Mdesign-documents/016-backoffice-order-management.rst | 22+++++++++++++++-------
Mdesign-documents/017-backoffice-inventory-management.rst | 16+++++++++++++++-
Mdesign-documents/018-contract-json.rst | 25+++++++++++++++++++++----
Mdesign-documents/019-wallet-backup-merge.rst | 10++++++++++
Mdesign-documents/020-backoffice-rewards-management.rst | 13+++++++++++++
Mdesign-documents/021-exchange-key-continuity.rst | 19+++++++++++++++++--
Mdesign-documents/022-wallet-auditor-reports.rst | 12+++++++++++-
Mdesign-documents/023-taler-kyc.rst | 30+++++++++++++++++++++++++++---
Mdesign-documents/024-age-restriction.rst | 25++++++++++++++++++++-----
Mdesign-documents/025-withdraw-from-wallet.rst | 14++++++++++++++
Mdesign-documents/026-refund-fees.rst | 9+++++++++
Mdesign-documents/027-sandboxing-taler.rst | 11+++++++++--
Mdesign-documents/028-deposit-policies.rst | 16+++++++++++++---
Mdesign-documents/029-mobile-ui.rst | 12++++++++++++
Mdesign-documents/030-offline-payments.rst | 12++++++++++++
Mdesign-documents/031-invoicing.rst | 20+++++++++++++++++---
Mdesign-documents/032-brandt-vickrey-auctions.rst | 13+++++++++++++
Mdesign-documents/033-database.rst | 25++++++++++++++++++++-----
Mdesign-documents/034-wallet-db-migration.rst | 47+++++++++++++++++++++++++++++++++++------------
Mdesign-documents/035-regional-currencies.rst | 9+++++++++
Mdesign-documents/036-currency-conversion-service.rst | 19++++++++++++++-----
Mdesign-documents/037-wallet-transactions-lifecycle.rst | 14+++++++++++---
Mdesign-documents/038-demobanks-protocol-suppliers.rst | 17+++++++++++++++--
Mdesign-documents/039-taler-browser-integration.rst | 25+++++++++++++++++++++++--
Mdesign-documents/040-distro-packaging.rst | 21+++++++++++++++------
Mdesign-documents/041-wallet-balance-amount-definitions.rst | 8++++++++
Mdesign-documents/042-synthetic-wallet-errors.rst | 9+++++++++
Mdesign-documents/043-managing-prebuilt-artifacts.rst | 8++++++++
Mdesign-documents/044-ci-system.rst | 14++++++++++++++
Mdesign-documents/045-kyc-inheritance.rst | 20+++++++++++++++-----
Mdesign-documents/046-mumimo-contracts.rst | 48+++++++++++++++++++++++++++++++-----------------
Mdesign-documents/047-stefan.rst | 21+++++++++++++++------
Mdesign-documents/048-wallet-exchange-lifecycle.rst | 28+++++++++++++++++++---------
Mdesign-documents/049-auth.rst | 32++++++++++++++++++++++++--------
Mdesign-documents/050-libeufin-nexus.rst | 31++++++++++++++++++++++++-------
Mdesign-documents/051-fractional-digits.rst | 20+++++++++++++++-----
Mdesign-documents/052-libeufin-bank-2fa.rst | 19+++++++++++++++++--
Mdesign-documents/053-wallet-ui.rst | 14++++++++++++++
Mdesign-documents/054-dynamic-form.rst | 15+++++++++++++++
Mdesign-documents/055-wallet-problem-report.rst | 17++++++++++-------
Mdesign-documents/056-weblate-integration.rst | 24+++++++++++++++++++++---
Mdesign-documents/057-libeufin-bank-account-lockout.rst | 26+++++++++++++++++++++++---
Mdesign-documents/058-ebics-tx-unique-id.rst | 24++++++++++++++++++++++--
Mdesign-documents/059-statistics.rst | 18++++++++++++++----
Mdesign-documents/060-clause-schnorr.rst | 33+++++++++++++++++++++++++--------
Mdesign-documents/061-batched-withdraw.rst | 38++++++++++++++++++++++++++++----------
Mdesign-documents/062-pq-refresh.rst | 17+++++++++++++++++
Mdesign-documents/063-libeufin-conversion-rate-classes.rst | 31+++++++++++++++++++++++++------
Mdesign-documents/064-kyc-operation-algo.rst | 14++++++++++++--
Mdesign-documents/065-exchange-base-url-migration.rst | 23+++++++++++++++++++----
Mdesign-documents/066-wallet-color-scheme.rst | 30+++++++++++++++++++++---------
Mdesign-documents/067-merchant-self-provisioning.rst | 25++++++++++++++++++++-----
Mdesign-documents/068-tokens-roadmap.rst | 25+++++++++++++++++++------
Mdesign-documents/069-exchange-base-url-completion.rst | 21++++++++++++++++-----
Mdesign-documents/070-alias-directory-mailbox.rst | 19++++++++++++++++++-
Mdesign-documents/071-auto-refresh.rst | 17+++++++++++++----
Mdesign-documents/072-products-units.rst | 37+++++++++++++++++++++++--------------
Mdesign-documents/073-extended-merchant-template.rst | 67++++++++++++++++++++++++++++++++++++++++++++++---------------------
Mdesign-documents/074-merchant-backend-simplification.rst | 16+++++++++-------
Mdesign-documents/075-wallet-bban-support.rst | 18++++++++++++++----
Mdesign-documents/076-paywall-proxy.rst | 32++++++++++++++++++++------------
Mdesign-documents/077-merchant-self-provisioning.rst | 13+++++++++++++
Mdesign-documents/078-taxes.rst | 25+++++++++++++++++++------
Mdesign-documents/079-reports.rst | 23+++++++++++++++--------
Mdesign-documents/080-short-wire-subject.rst | 33+++++++++++++++++++++++++++------
Mdesign-documents/081-shop-discovery.rst | 17+++++++++++++----
Mdesign-documents/082-wallet-diagnostics.rst | 25+++++++++++++++++++++++--
Mdesign-documents/083-wallet-initiated-withdrawal.rst | 7+++++++
Mdesign-documents/084-simple-observability.rst | 13++++++++++---
Mdesign-documents/085-transfer-status.rst | 11+++++++++--
Mdesign-documents/086-wallet-design.rst | 14++++++++++++++
Mdesign-documents/087-wallet-onboarding.rst | 8++++++++
Mdesign-documents/088-wallet-withdraw.rst | 10+++++++++-
Mdesign-documents/089-merchant-2fa.rst | 9++++++++-
Mdesign-documents/090-branding.rst | 12++++++++++--
Mdesign-documents/091-wallet-coin-selection.rst | 9+++++++++
Mdesign-documents/092-incremental-backup-sync.rst | 13+++++++++++++
Mdesign-documents/093-checkout-page.rst | 17++++++++++++-----
Mdesign-documents/094-discounts-passes-wallet.rst | 14++++++++++++--
Mdesign-documents/095-captcha-100.rst | 25+++++++++++++++----------
Mdesign-documents/096-partial-payments.rst | 19+++++++++++++++----
Mdesign-documents/097-challenge-confirmations.rst | 16+++++++++++++---
Mdesign-documents/098-token-fountains.rst | 8++++++++
Mdesign-documents/099-programmable-templates.rst | 7+++++++
Mdesign-documents/100-shares.rst | 12++++++++++++
Mdesign-documents/101-semantic-token-families.rst | 20+++++++++++++++-----
Mdesign-documents/999-template.rst | 31+++++++++++++++++++++++++++++++
Adesign-documents/README.rst | 84+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Mdesign-documents/index.rst | 11+++++++----
Mdeveloper/taler-developer-manual.rst | 68+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
Mdeveloper/taler-wallet-developer.rst | 168+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Mindex.rst | 1+
Mlibeufin/bank-manual.rst | 24++++++++++++++++++++++++
Mlibeufin/nexus-manual.rst | 23+++++++++++++++++++++++
Mtaler-exchange-manual.rst | 6++++--
Mtaler-merchant-manual.rst | 54+++++++++++++++++++++++++++++++++++++++++++++++++++++-
Awallet/browser-integration.rst | 103+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Awallet/index.rst | 19+++++++++++++++++++
127 files changed, 2268 insertions(+), 583 deletions(-)

diff --git a/core/api-bank-integration.rst b/core/api-bank-integration.rst @@ -37,10 +37,10 @@ The current protocol version is **v5**. * ``v5``: adds ``no_amount_to_wallet`` flag to the WOPID status -**Upcoming versions:** - -* ``vSHORT``: support for short wire transfer subjects? -* ``vPERIODIC``: support for periodic wire transfers? +Prepared short and recurring wire-transfer subjects are specified by the +separate :ref:`Taler Prepared Transfer HTTP API +<taler-prepared-transfer-http-api>` and do not require a Bank Integration API +version bump. **Ideas for future version:** diff --git a/core/api-mailbox.rst b/core/api-mailbox.rst @@ -27,7 +27,7 @@ without having to interact with the respective messaging service. Clients (wallets) are expected to generate mailbox keys that uniquely identify a mailbox as well as encryption keys that can be used to encrypt messages for -the mailbox (e.g. `HPKE <https://www.rfc-editor.org/rfc/rfc9180.html>`_. +the mailbox (e.g. `HPKE <https://www.rfc-editor.org/rfc/rfc9180.html>`_). Mailboxes must be registered along with their public key information. Registration may incur costs depending on the mailbox service provider used. @@ -44,7 +44,8 @@ Version History The current protocol version is **v0**. -* Nothing depends on the mailbox API at this point. +* Wallet-core uses this API to exchange push and pull payment requests after + mailbox initialization. **Version history:** diff --git a/core/api-merchant.rst b/core/api-merchant.rst @@ -860,6 +860,42 @@ initially labeling these order components as forgettable, the merchant can later tell the backend to forget those details (without changing the hash of the contract!) to minimize risks from information leakage. +A member is marked as forgettable by adding its name to the +``$forgettable`` object in the same parent object. The value is a random salt +encoded using upper-case Crockford Base32. Order-creation requests may use +``true`` instead of a salt; the merchant backend then generates the random +salt before producing the final contract terms. The boolean form is not valid +in final contract terms. + +Forgetting a member removes both its value and its salt and adds an entry with +the same name to ``$forgotten``. The entry is a 64-byte HKDF-SHA-512 result, +encoded using upper-case Crockford Base32. The HKDF input key material is the +RFC 8785 canonical JSON representation of the recursively scrubbed member +value followed by one zero byte. The HKDF salt is the UTF-8 representation of +the salt string followed by one zero byte, and the HKDF context is empty. Scrubbing an object +recursively forgets all members marked by ``$forgettable``. These rules make +the hash of the contract terms invariant under authorized forgetting. + +Objects that participate in this mechanism may use ordinary member names +matching ``^[-0-9A-Za-z_]+$`` and the two reserved names ``$forgettable`` and +``$forgotten``. Numbers must be safe integers; floating-point values are not +permitted. + +The following object is the interoperability reference vector:: + + { + "k1": 1, + "$forgettable": { "k1": "SALT" }, + "k2": { + "n1": true, + "$forgettable": { "n1": "salt" } + }, + "k3": { "n1": "string" } + } + +Its Crockford-Base32-encoded contract hash is +``VDE8JPX0AEEE3EX1K8E11RYEWSZQKGGZCV6BWTE4ST1C8711P7H850Z7F2Q2HSSYETX87ERC2JNHWB7GTDWTDWMM716VKPSRBXD7SRR``. + .. include:: merchant/patch-private-orders-ORDER_ID-forget.rst .. include:: merchant/delete-private-orders-ORDER_ID.rst @@ -2386,7 +2422,7 @@ listing it in the exchanges array. In addition to the fields described above, each object (from `ContractTerms` down) can mark certain fields as "forgettable" by listing the names of those fields -in a special peer field ``_forgettable``. +in a special peer field ``$forgettable``. (See :ref:`Private order data cleanup <private-order-data-cleanup>`.) diff --git a/core/api-taldir.rst b/core/api-taldir.rst @@ -46,7 +46,8 @@ Version History The current protocol version is **v0**. -* Nothing depends on the mailbox API at this point. +* Wallet-core uses the Directory API to register and resolve aliases for + mailbox-based wallet-to-wallet communication. **Version history:** diff --git a/core/bank-transfer/post-registration.rst b/core/bank-transfer/post-registration.rst @@ -27,7 +27,7 @@ interface RegistrationRequest { // Payto URI of the credit account - credit_account: Amount; + credit_account: string; // Transfer types type: "reserve" | "kyc"; diff --git a/core/exchange/get-keys.rst b/core/exchange/get-keys.rst @@ -196,15 +196,6 @@ // The exchange's signing keys. signkeys: SignKey[]; - // Optional field with a dictionary of (name, object) pairs defining the - // supported and enabled extensions, such as ``age_restriction``. - extensions?: { name: ExtensionManifest }; - - // Signature by the exchange master key of the SHA-256 hash of the - // normalized JSON-object of field extensions, if it was set. - // The signature has purpose TALER_SIGNATURE_MASTER_EXTENSIONS. - extensions_sig?: EddsaSignature; - } The specification for the account object is: diff --git a/core/exchange/post-batch-deposit.rst b/core/exchange/post-batch-deposit.rst @@ -133,15 +133,7 @@ // Date until which the merchant can issue a refund to the customer via the // exchange, to be omitted if refunds are not allowed. - // - // THIS FIELD WILL BE DEPRECATED, once the refund mechanism becomes a - // policy via extension. refund_deadline?: Timestamp; - - // CAVEAT: THIS IS WORK IN PROGRESS - // (Optional) policy for the batch-deposit. - // This might be a refund, auction or escrow policy. - policy?: DepositPolicy; } .. ts:def:: BatchDepositRequestCoin @@ -198,142 +190,6 @@ } - .. ts:def:: DepositPolicy - - type DepositPolicy = - | PolicyMerchantRefund - | PolicyBrandtVickreyAuction - | PolicyEscrowedPayment; - - .. ts:def:: PolicyMerchantRefund - - // CAVEAT: THIS IS STILL WORK IN PROGRESS. - // This policy is optional and might not be supported by the exchange. - // If it does, the exchange MUST show support for this policy in the - // ``extensions`` field in the response to ``/keys``. - interface PolicyMerchantRefund { - type: "merchant_refund"; - - // EdDSA `public key of the merchant <merchant-pub>`, so that the client - // can identify the merchant for refund requests. - merchant_pub: EddsaPublicKey; - - // Date until which the merchant can issue a refund to the customer via - // the ``/extensions/policy_refund``-endpoint of the exchange. - deadline: Timestamp; - } - - .. ts:def:: PolicyBrandtVickreyAuction - - // CAVEAT: THIS IS STILL WORK IN PROGRESS. - // This policy is optional and might not be supported by the exchange. - // If it does, the exchange MUST show support for this policy in the - // ``extensions`` field in the response to ``/keys``. - interface PolicyBrandtVickreyAuction { - type: "brandt_vickrey_auction"; - - // Public key of this bidder. - // - // The bidder uses this key to sign the auction information and - // the messages it sends to the seller during the auction. - bidder_pub: EddsaPublicKey; - - // Hash of the auction terms - // - // The hash should be taken over a normalized JSON object of type - // `BrandtVickreyAuction`. - h_auction: HashCode; - - // The amount that this bidder commits to for this auction - // - // This amount can be larger than the contribution of a single coin. - // The bidder can increase funding of this auction policy by using - // sufficiently many coins during the deposit operation (single or batch) - // with the same policy. - commitment: Amount; - - // Date until the auction must have been successfully executed and - // a valid transcript provided to the - // ``/extensions/policy_brandt_vickrey_auction``-endpoint of the - // exchange. - // - // [If the auction has not been executed by then] OR [has been executed - // before then, but this bidder did not win], the coin's value doesn't - // change and the owner can refresh the coin. - // - // If this bidder won the auction, the winning price/amount from the - // outcome will be substracted from the coin and transfered to the - // merchant's ``payout_uri`` from the deposit request (minus a potential - // auction fee). For any remaining value, the bidder can refresh the - // coin to retrieve change. - deadline: Timestamp; - } - - .. ts:def:: BrandtVickreyAuction - - // CAVEAT: THIS IS STILL WORK IN PROGRESS. - // This structure defines an auction of Brandt-Vickory kind. - // It is used for the `PolicyBrandtVickreyAuction`. - interface BrandtVickreyAuction { - // Start date of the auction - time_start: Timestamp; - - // Maximum duration per round. There are four rounds in an auction of - // Brandt-Vickrey kind. - time_round: RelativeTime; - - // This integer m refers to the (m+1)-type of the Brandt-Vickrey-auction. - // - Type 0 refers to an auction with one highest-price winner, - // - Type 1 refers to an auction with one winner, paying the second - // highest price, - // - Type 2 refers to an auction with two winners, paying - // the third-highest price, - // - etc. - auction_type: Integer; - - // The vector of prices for the Brandt-Vickrey auction. The values MUST - // be in strictly increasing order. - prices: Amount[]; - - // The type of outcome of the auction. - // In case the auction is declared public, each bidder can calculate the - // winning price. This field is not relevant for the replay of a - // transcript, as the transcript must be provided by the seller who sees - // the winner(s) and winning price of the auction. - outcome_public: boolean; - - // The public key of the seller. - pubkey: EddsaPublicKey; - - // The seller's account details as a full payto URI. - payto_uri: string; - } - - - .. ts:def:: PolicyEscrowedPayment - - // CAVEAT: THIS IS STILL WORK IN PROGRESS - // This policy is optional and might not be supported by the exchange. - // If it does, the exchange MUST show support for this policy in the - // ``extensions`` field in the response to ``/keys``. - interface PolicyEscrowedPayment { - type: "escrowed_payment"; - - // Public key of this trustor, the owner of the coins. - // - // To claim the deposit, the merchant must provide the valid signature - // of the ``h_contract_terms`` field from the deposit, signed by _this_ - // key, to the ``/extensions/policy_escrow``-endpoint of the exchange, - // after the date specified in ``not_before`` and before the date - // specified in ``not_after``. - trustor_pub: EddsaPublicKey; - - // Latest date by which the deposit must be claimed. If the deposit - // has not been claimed by that date, the deposited coins can be - // refreshed by the (still) owner. - deadline: Timestamp; - } - The deposit operation succeeds if the coin is valid for making a deposit and has enough residual value that has not already been deposited or melted. diff --git a/core/exchange/post-coins-COIN_PUB-refund.rst b/core/exchange/post-coins-COIN_PUB-refund.rst @@ -66,6 +66,11 @@ **Details:** + The deposit fee is waived only when the cumulative refunds for this + particular coin return its full deposited contribution. A partial refund, + or a full refund of an order that leaves this coin only partially refunded, + does not waive the coin's deposit fee. + .. ts:def:: RefundRequest interface RefundRequest { diff --git a/core/exchange/post-reveal-melt.rst b/core/exchange/post-reveal-melt.rst @@ -90,8 +90,8 @@ // IFF the denomination of the old coin had support for age restriction, // the client MUST provide the original age commitment, i. e. the // vector of public keys, or omitted otherwise. - // The size of the vector MUST be the number of age groups as defined by the - // Exchange in the field ``.age_groups`` of the extension ``age_restriction``. + // The size of the vector MUST be the number of age groups configured by + // the exchange for age restriction. age_commitment?: Edx25519PublicKey[]; } diff --git a/core/mailbox/get-H_MAILBOX.rst b/core/mailbox/get-H_MAILBOX.rst @@ -32,4 +32,5 @@ :http:statuscode:`429 Too Many Requests`: The system is currently experiencing a too high request load and is unable to accept the message for delivery. - The response format is given by :ref:`MailboxRateLimitedResponse`. + The response body is a ``MailboxRateLimitedResponse`` as defined by the + message-delivery endpoint. diff --git a/core/mailbox/get-info-H_MAILBOX.rst b/core/mailbox/get-info-H_MAILBOX.rst @@ -11,7 +11,8 @@ :http:statuscode:`429 Too Many Requests`: The system is currently experiencing a too high request load and is unable to accept the message for delivery. - The response format is given by :ref:`MailboxRateLimitedResponse`. + The response body is a ``MailboxRateLimitedResponse`` as defined by the + message-delivery endpoint. **Details:** diff --git a/core/merchant/get-private-statistics-amount-SLUG.rst b/core/merchant/get-private-statistics-amount-SLUG.rst @@ -1,7 +1,7 @@ .. http:get:: /management/instances/$INSTANCE/statistics-amount/$SLUG .. http:get:: [/instances/$INSTANCE]/private/statistics-amount/$SLUG - This request will return be used to statistics where the + This request returns statistics where the values are amounts. All available values for the given SLUG will be returned. Since protocol **v25**. diff --git a/core/merchant/get-private-statistics-counter-SLUG.rst b/core/merchant/get-private-statistics-counter-SLUG.rst @@ -1,7 +1,7 @@ .. http:get:: /management/instances/$INSTANCE/statistics-counter/$SLUG .. http:get:: [/instances/$INSTANCE]/private/statistics-counter/$SLUG - This request will return be used to statistics where the + This request returns statistics where the values are counters. All available values for the given SLUG will be returned. Since protocol **v25**. diff --git a/core/merchant/get-private-statistics-report-NAME.rst b/core/merchant/get-private-statistics-report-NAME.rst @@ -1,16 +1,20 @@ .. http:get:: [/instances/$INSTANCE]/private/statistics-report/$NAME .. http:get:: /management/instances/$INSTANCE/statistics-report/$NAME - This request will return be used to generate a specific - report based on $NAME. The backend **MAY** support generating - the report in various formats. Supported values for ``$NAME`` include: + This request generates a specific report based on ``$NAME``. The backend + **MAY** support generating the report in various formats. The currently + implemented value is: * "transactions" (total revenue, total refunds, fees as well as number of transactions), since **v25** - * "money-pots" (changes to totals in money pots), since **v25** - * "taxes" (amount of taxes withheld by tax class), since **vTAXES**, + + Reserved names for upcoming report implementations are: + + * "money-pots" (changes to totals in money pots), + * "taxes" (amount of taxes withheld by tax class), planned for + **vTAXES**, * "sales-funnel" (number and volume of orders - created, claimed, paid, refunded and settled), since **vXXX**, + created, claimed, paid, refunded and settled). The overall endpoint family exists since protocol **v25**. @@ -50,7 +54,7 @@ The requested statistical data is unavailable because it is not kept at the requested granularity for this long. Returned with an error code of - ``TALER_EC_MERCHANT_PRIVATE_GET_STATISTICS_REPORT_GRANULARITY_UNAVAILABLE,`` + ``TALER_EC_MERCHANT_PRIVATE_GET_STATISTICS_REPORT_GRANULARITY_UNAVAILABLE``. :http:statuscode:`501 Not implemented`: The requested functionality is not implemented. Usually returned if the PDF generator is not available diff --git a/design-documents/001-new-browser-integration.rst b/design-documents/001-new-browser-integration.rst @@ -1,6 +1,14 @@ XX 01: New Browser Integration ############################## +:Design status: Superseded +:Implementation status: Partial +:DD shepherd: TBD +:Historical contributors: Florian Dold +:First published: 2020-04-08 +:Last substantive change: 2023-09-15 +:Superseded by: :doc:`039-taler-browser-integration` + .. warning:: We have decided not to follow through with the proposed solution in this @@ -26,6 +34,8 @@ XX 01: New Browser Integration encourage merchants to treat mobile / detached wallets as 2nd class citizens. + The body below is retained for historical context and is non-normative. + Summary ======= diff --git a/design-documents/002-wallet-exchange-management.rst b/design-documents/002-wallet-exchange-management.rst @@ -1,12 +1,24 @@ XX 02: Wallet Exchange Management ################################# +:Design status: Superseded +:Implementation status: Implemented +:DD shepherd: TBD +:Historical contributors: Florian Dold, Torsten Grote, Christian Grothoff +:First published: 2020-04-09 +:Last substantive change: 2023-09-15 +:Implementation evidence: taler-typescript-core (2024-01-16) +:Superseded by: :doc:`048-wallet-exchange-lifecycle` +:Normative references: :doc:`../wallet/wallet-core` + .. note:: This design document is deprecated in favor of DD48. Trusted exchanges and auditors are no longer something we have. + The body below documents the old trust model and is non-normative. + Summary ======= diff --git a/design-documents/003-tos-rendering.rst b/design-documents/003-tos-rendering.rst @@ -1,6 +1,15 @@ DD 03: ToS rendering #################### +:Design status: Accepted +:Implementation status: Implemented +:DD shepherd: TBD +:Historical contributors: Florian Dold, Torsten Grote, Christian Grothoff +:First published: 2020-04-23 +:Last substantive change: 2023-04-06 +:Implementation evidence: exchange (2019-12-08, 2020-02-07) +:Normative references: :doc:`../core/tos` + Summary ======= @@ -25,13 +34,13 @@ Proposed Solution Internationalization -------------------- -The server will parse the ``Accept-Languages`` request header to determine +The server will parse the ``Accept-Language`` request header to determine which language the user will most likely want to read the terms of service in. If multiple languages are given, the server will check against the available languages and return the one with the highest preference. Additionally, the server will return an ``Avail-Languages`` header which -details what other langauges the terms of service are available in. The +details what other languages the terms of service are available in. The user interface in the wallet should then allow the user to switch to one of these alternatives using some language switcher. diff --git a/design-documents/004-wallet-withdrawal-flow.rst b/design-documents/004-wallet-withdrawal-flow.rst @@ -1,6 +1,15 @@ DD 04: Wallet Withdrawal Flow ############################# +:Design status: Accepted +:Implementation status: Implemented +:DD shepherd: TBD +:Historical contributors: Torsten Grote +:First published: 2020-04-23 +:Last substantive change: 2020-07-20 +:Implementation evidence: taler-typescript-core (2022-08-26) +:Normative references: :doc:`048-wallet-exchange-lifecycle`, :doc:`../wallet/wallet-core` + Summary ======= @@ -24,7 +33,8 @@ There are three screens involved in the process: 1. **Select exchange**: Here the user can pick an exchange from a list of known exchanges or add a new one for immediate use. - For details see :doc:`002-wallet-exchange-management`. + For the current lifecycle and selection model see + :doc:`048-wallet-exchange-lifecycle`. 2. **Display an exchange's Terms of Service**: Shows the terms and gives an option to accept them. For details see :doc:`003-tos-rendering`. diff --git a/design-documents/005-wallet-backup-sync.rst b/design-documents/005-wallet-backup-sync.rst @@ -1,14 +1,24 @@ XX 05: Wallet Backup and Sync ############################# +:Design status: Superseded +:Implementation status: Prototype +:DD shepherd: TBD +:Historical contributors: Florian Dold, Torsten Grote, Christian Grothoff +:First published: 2020-04-27 +:Last substantive change: 2023-09-15 +:Superseded by: :doc:`092-incremental-backup-sync` + .. warning:: - This document is deprecated. We have decided to first - implement backup, and tackle sync later. + This document is deprecated and superseded by DD92, which specifies an + incremental backup and multi-device synchronization protocol. The multi-device sync described in this document would lead to a bad/unexpected user experience that does not justify the conceptual / implementation complexity. + The body below is retained for historical context and is non-normative. + Summary ======= diff --git a/design-documents/006-extensions.rst b/design-documents/006-extensions.rst @@ -1,12 +1,21 @@ XX 06: Extensions for GNU Taler ############################### +:Design status: Accepted +:Implementation status: Removed +:DD shepherd: TBD +:Historical contributors: Özgür Kesim, Florian Dold +:First published: 2021-10-14 +:Last substantive change: 2026-07-28 +:Implementation evidence: exchange (2026-05-31) .. attention:: As of 2026-07-28, the extension mechanism has been retired. + The body below describes the retired mechanism and is non-normative. + Summary ======= diff --git a/design-documents/007-payment.rst b/design-documents/007-payment.rst @@ -1,6 +1,21 @@ DD 07: Specification of the Payment Flow ######################################## +:Design status: Accepted +:Implementation status: Implemented +:DD shepherd: TBD +:Historical contributors: Florian Dold, Christian Grothoff, Thien-Thi Nguyen +:First published: 2020-08-09 +:Last substantive change: 2020-10-31 +:Implementation evidence: merchant (2020-07-21, 2020-08-16) +:Normative references: :doc:`../core/api-merchant`, :doc:`../wallet/wallet-core` + +.. note:: + + This document records the original browser payment-flow design. The + current merchant and wallet APIs are authoritative for implemented endpoint + behavior; unresolved questions below are historical. + Summary ======= @@ -221,7 +236,7 @@ The following example uses a detached wallet: B: -> GET https://shop.demo.taler.net/books/moby-dick (content-type: application/html) - S: -> GET https://merchant-backend.demo.taler.net/orders/ord01?session_id-sess01 + S: -> GET https://merchant-backend.demo.taler.net/orders/ord01?session_id=sess01 S: <- HTTP 200, order status "paid" B: <- HTTP 200, content of "moby-dick" is rendered diff --git a/design-documents/008-fees.rst b/design-documents/008-fees.rst @@ -1,10 +1,20 @@ XX 08: Fee Structure Metrics ############################ +:Design status: Abandoned +:Implementation status: Not started +:DD shepherd: TBD +:Historical contributors: Florian Dold, Christian Grothoff, Stefan Kügel, Thien-Thi Nguyen +:First published: 2020-08-09 +:Last substantive change: 2023-09-15 + .. note:: This design document is deprecated. + The incomplete proposal below is retained for historical context and is + non-normative. + Summary ======= diff --git a/design-documents/009-backup.rst b/design-documents/009-backup.rst @@ -1,11 +1,21 @@ XX 09: Wallet Backup #################### +:Design status: Superseded +:Implementation status: Prototype +:DD shepherd: TBD +:Historical contributors: Florian Dold, Christian Grothoff, Iván Ávalos +:First published: 2020-11-06 +:Last substantive change: 2026-08-09 +:Superseded by: :doc:`092-incremental-backup-sync` + .. warning:: This design document is deprecated. The incremental backup and sync protocol described in `DD 92`_ supersedes it. + The body below is retained for historical context and is non-normative. + .. _DD 92: https://docs.taler.net/design-documents/092-incremental-backup-sync.html Summary diff --git a/design-documents/010-exchange-helpers.rst b/design-documents/010-exchange-helpers.rst @@ -1,11 +1,20 @@ DD 10: Exchange crypto helper design #################################### +:Design status: Accepted +:Implementation status: Implemented +:DD shepherd: TBD +:Historical contributors: Christian Grothoff, Thien-Thi Nguyen +:First published: 2020-11-22 +:Last substantive change: 2021-01-11 +:Implementation evidence: exchange (2020-11-21, 2020-11-22, 2021-01-17, 2022-01-03) +:Normative references: :doc:`../taler-exchange-manual`, :doc:`../core/api-exchange` + Summary ======= A way to minimize the attack surface for extraction of the private online -signing keys (RSA and EdDSA) from the exchange is described. +signing keys (RSA, Clause-Schnorr and EdDSA) from the exchange is described. Motivation @@ -28,7 +37,7 @@ Requirements * Ideally, we should be able to determine the number of signatures obtained illicitly by the attacker. * Key management for operators should be simplified to improve usability. -* Both RSA and EdDSA online signing keys need to be protected. +* RSA, Clause-Schnorr and EdDSA online signing keys need to be protected. * We should have a way to verify that the keys signed with the offline master private key are those originating from the isolated (software/hardware) security module. @@ -37,7 +46,7 @@ Requirements Proposed Solution ================= -The private keys are to be created, used and deleted by two helper processes +The private keys are created, used and deleted by three helper processes running under a different user ID (UID), creating in effect a software security module. The exchange's HTTP process will be required to interact with those helpers via a UNIX domain socket. @@ -86,10 +95,8 @@ Helper design details: Exchange design considerations: * The helpers are started by the system, say via systemd, not by the - exchange. This simplifies the exchange, and we already needed the - exchange operator to start four processes to operate an exchange. - So this number simply increases to six (not even counting the - PostgreSQL database and a reverse HTTP proxy for TLS termination). + exchange. This simplifies the exchange. The exact number of exchange + processes is deployment-specific and has grown since the original design. * Each exchange thread will create its own connection to the helpers, and will block while waiting on the helper to create a signature. This keeps the exchange logic simple and similar to the existing in-line signing calls. @@ -102,18 +109,18 @@ Exchange design considerations: New exchange endpoints: -* The exchange will expose the corresponding public keys via a GET to - ``/keys/future`` endpoint to the offline signing process. For offline +* The exchange exposes the corresponding public keys via a GET to the + ``/management/keys`` endpoint to the offline signing process. For offline signing, tooling will be provided to first download to a file, then sign based on that file, and then upload the resulting signature back to - the exchange. For this, master signatures will be POSTed to - the exchange to the ``/keys`` endpoint. + the exchange. For this, master signatures are POSTed to + the exchange at the ``/management/keys`` endpoint. The exchange will keep those signatures in the PostgreSQL database. -* A new endpoint (``/auditors``) will also allow adding/removing auditors - (POST, DELETE) using requests signed with the offline master private key. - Once an auditor has been added, the respective auditor signatures on exchange - keys can also be POSTed to the REST API at - ``/auditors/$AUDITOR_PUB/{denomination,signing}``. +* The ``/management/auditors`` endpoint enables auditors, and + ``/management/auditors/$AUDITOR_PUB/disable`` disables them, using requests + signed with the offline master private key. Auditor signatures on + denominations are POSTed to + ``/auditors/$AUDITOR_PUB/$H_DENOM_PUB``. Overall, the result is that except for software updates and the fundamental configuration, the ``taler-exchange-http`` will be updated only via HTTP(S) diff --git a/design-documents/011-auditor-db-sync.rst b/design-documents/011-auditor-db-sync.rst @@ -1,9 +1,24 @@ DD 11: Auditor-Exchange Database Synchronization ################################################ +:Design status: Accepted +:Implementation status: Implemented +:DD shepherd: TBD +:Historical contributors: Christian Grothoff, Thien-Thi Nguyen +:First published: 2021-01-01 +:Last substantive change: 2021-01-06 +:Implementation evidence: exchange (2021-01-11, 2026-08-01) +:Normative references: :doc:`../taler-auditor-manual` + Summary ======= +.. note:: + + This document records the design rationale. The auditor manual and the + current database schema are authoritative for operational details and the + set of synchronized tables. + Ways for the auditor to obtain a current copy of the exchange database (to verify that the exchange is operating correctly) are discussed. diff --git a/design-documents/012-fee-schedule-metrics.rst b/design-documents/012-fee-schedule-metrics.rst @@ -1,9 +1,18 @@ DD 12: Exchange Fee Configuration ################################# +:Design status: Draft +:Implementation status: Partial +:DD shepherd: TBD +:Historical contributors: Stefan Kügel, Christian Grothoff +:First published: 2021-01-07 +:Last substantive change: 2021-12-09 +:Normative references: :doc:`../core/api-exchange` + .. note:: - This document is a draft. + This document is a historical draft and is non-normative. The current + exchange API is authoritative for the available fee types. Summary ======= @@ -32,7 +41,9 @@ ensure that attackers which try to overwhelm the Exchange infrastructure with unusually large numbers of transactions proportionally contribute to the Exchange's infrastructure budget. -There are six fee types available for configuration by the Exchange operator: +The original design considered the following six fee types. The current +protocol additionally defines global account, history, purse and +exchange-to-exchange transfer fees; see the normative exchange API. 1. **Withdraw**: For each successful withdrawal from the checking account, **per coin** 2. **Deposit**: For spending, **per coin** @@ -119,8 +130,8 @@ conflicting criteria: * Fees chosen by Exchange operators have to be explained to the users in the terms of service of the Exchange. Thus, any proposed solution should consider its impact on usability and comprehension. -* The refresh transaction is automatically triggered by the wallet software - 3 months before the end of the validity of a coin. Especially if Exchange +* A refresh transaction can be triggered automatically by wallet policy before + the end of the validity of a coin. Especially if Exchange operators charge **refresh** fees, the fact that a fee may automatically be charged in the background without user interaction is likely particularly difficult to explain. @@ -309,7 +320,8 @@ In contrast to the **refresh** fees, the sellers -- and not the buyers -- trigger refunds. If an Exchange charges **refund** fees, the already deposited coins of the buyers would be charged with this fee in case of a partial or full refund. If a **refund** fee is charged for a coin, the respective -**deposit** fee is waived. +**deposit** fee is waived only when the refund is a full refund of that +specific coin, as specified in DD26. From the buyers' point of view, therefore, the sellers should legitimately bear this fee, alas this is not possible given that sellers do not inherently diff --git a/design-documents/013-peer-to-peer-payments.rst b/design-documents/013-peer-to-peer-payments.rst @@ -3,9 +3,23 @@ DD 13: Wallet-to-Wallet Payments ################################ +:Design status: Accepted +:Implementation status: Implemented +:DD shepherd: TBD +:Historical contributors: Florian Dold, Christian Grothoff, Sebastian +:First published: 2021-01-18 +:Last substantive change: 2022-06-03 +:Implementation evidence: exchange (2022-03-20, 2022-03-24), taler-typescript-core (2022-07-12, 2022-08-23) +:Normative references: :doc:`../core/api-exchange`, :doc:`../wallet/wallet-core`, :doc:`037-wallet-transactions-lifecycle` + Summary ======= +.. note:: + + This document includes historical protocol sketches followed by later + refinements. The current exchange and wallet APIs are authoritative. + This design document proposes an extension of the Taler protocol that allows payments from wallet-to-wallet without a merchant. @@ -123,7 +137,8 @@ Requirements ============ * The protocol must permit transacting arbitrary amounts in any currency, - as long as both parties trust the exchange involved. + as long as the exchanges involved support the necessary purse and partner + operations. * The control data for wallet-to-wallet payments should be small enough to fit into a QR code or short message (so ideally less than 64 bytes). * No other direct communication channel between payer and payee should @@ -369,20 +384,22 @@ Payment offers In this protocol variant, the payer is initiating the process. 1. The payer creates a **purse** by computing a public-private key pair. -2. The payer POSTs to the ``/purse/$PURSE_PUB/depost`` endpoint to - deposit coins into the purse and optionally upload the encrypted contract terms. +2. The payer POSTs to the ``/purses/$PURSE_PUB/create`` endpoint to create the + purse, deposit coins and optionally upload the encrypted contract terms. The deposit signatures should use ``payto://taler/$PURSE_PUB`` as the target address and signing over the ``$CONTRACT_HASH`` as usual in deposit operations. Note that the lack of a hostname indicates that the target address is a local purse. -3. The payer shares the purse's private key and the base URL +3. The payer shares the contract private key and the base URL of the exchange where the purse was created with the payee. - This can be done using a ``taler://purse/$BASE_URL/$PURSE_PRIV`` URL. + This is represented by a + ``taler://pay-push/$BASE_URL/$CONTRACT_PRIV`` URI in the implemented + protocol. The chapter on ``Refinements`` below clarifies why this step is not quite OK and was modified when implementing the design. -4. The payee uses the new ``/purse/$PURSE_PUB`` endpoint to retrieve - the encrypted contract (if available) and purse balance, which includes all - (coin) deposits and **merges** involving the purse. +4. The payee uses ``/contracts/$CONTRACT_PUB`` to retrieve the encrypted + contract and ``/purses/$PURSE_PUB/deposit`` to retrieve the purse status, + including its balance. 5. The payee's wallet must ensure that either: a. The purse has an attached encrypted contract terms, the contract @@ -392,8 +409,8 @@ In this protocol variant, the payer is initiating the process. contract terms of the purse. If neither case applies, the payee's wallet must reject the payment. -6. The payee can then POST to ``/purse/$PURSE_PUB/merge`` a - request signed by the purse's private key to **merge** the +6. The payee can then POST to ``/purses/$PURSE_PUB/merge`` a + request signed by the merge private key to **merge** the funds into an account. A second signature must be provided by the account private key, signing the ``$CONTRACT_HASH`` thereby affirming that the payee accepted the contract. @@ -412,7 +429,7 @@ In this protocol variant, the payer is initiating the process. affirm to the users that the transaction is final (even if it may not be instantly available to the payee if the payee did not complete the KYC process for the account). -9. The payer uses the GET ``/purse/$PURSE_PUB`` endpoint +9. The payer uses the GET ``/purses/$PURSE_PUB/merge`` endpoint to obtain the receipt from the payee (in the form of the **merge** signature). Query parameters are used to avoid downloading the (already known) encrypted contract and the @@ -425,24 +442,22 @@ Payment requests ---------------- 1. The payee creates a **purse** by computing a public-private key pair. -2. The payee POSTs to the ``/purse/$PURSE_PUB/merge`` endpoint to - both upload the encrypted contract, associate it with the payee's - account and signal its agreement to the contract. The - **merge** request must be signed by the purse's private key. - A second signature must be provided by the account private key, - signing the ``$CONTRACT_HASH`` thereby affirming that the payee - accepted the contract. -3. The payee provides the ``$PURSE_PRIV`` to the payer. -4. The payer computes the corresponding public key and uses the - new ``/purse/$PURSE_PUB`` endpoint to retrieve - the encrypted contract and the merge request, which signifies that - the payee would agree to the contract. +2. The payee POSTs to the ``/reserves/$RESERVE_PUB/purse`` endpoint to + create the purse, upload the encrypted contract, associate it with the + payee's account and signal its agreement to the contract. The request + includes signatures made with the purse, merge and account private keys. +3. The payee provides a + ``taler://pay-pull/$BASE_URL/$CONTRACT_PRIV`` URI to the payer. +4. The payer computes the corresponding public keys and uses + ``/contracts/$CONTRACT_PUB`` to retrieve the encrypted contract and + ``/purses/$PURSE_PUB/merge`` to retrieve the merge status, which signifies + that the payee would agree to the contract. 5. The payer software decrypts the encrypted contract using the purse private key and the payer accepts the contract in the user interface. 6. Processing continues depending on the source of the coins: a. If the payer's coins originate from the same exchange, the - payer software POSTs to the ``/purse/$PURSE_PUB/depost`` endpoint to + payer software POSTs to the ``/purses/$PURSE_PUB/deposit`` endpoint to deposit coins into the purse. The deposit signatures should use ``payto://taler/$PURSE_PUB`` as the target address and signing over the ``$CONTRACT_HASH`` as @@ -457,7 +472,7 @@ Payment requests 7. The exchange confirms the deposit. This allows the payer software to instantly affirm to the users that the transaction is final, or to abort or try again in case of errors. -8. The payee uses the GET ``/purse/$PURSE_PUB`` endpoint (possibly with long-polling) +8. The payee uses the GET ``/purses/$PURSE_PUB/deposit`` endpoint (possibly with long-polling) to be notified about the successful deposit and subsequent completion of the **merge** request. @@ -530,7 +545,7 @@ Cross-exchange W2W payment request: Alice wants her money back. She creates a request for payment in her wallet. The wallet creates a purse for 15 EUR at the only exchange that Alice is currently using. The wallet shows her a - ``taler://purse/{EXCHANGE_URL}/{PURSE_PRIV}`` + ``taler://pay-pull/{EXCHANGE_URL}/{CONTRACT_PRIV}`` link that she can share with Bob. Bob receives the link and opens it with his Taler wallet. Bob is using a different EUR exchange than Alice. Bob's wallet makes a ``/deposit`` request to his own exchange. Shortly after, Alice's @@ -549,7 +564,7 @@ Cross-exchange W2W payment offer: * Carol wants to send some money to Dave as a birthday gift. Carol knows that Dave is using Taler, but she does not know which exchange he is using. She opens her Taler wallet and initiates a P2P payment. She sends the resulting - ``taler://purse/{EXCHANGE_URL}/{PURSE_PRIV}`` in an e-mail to Dave. + ``taler://pay-push/{EXCHANGE_URL}/{CONTRACT_PRIV}`` in an e-mail to Dave. Dave opens the link in the e-mail with his Taler wallet. Since Dave is using a different exchange than Carol, Dave's wallet issues a **merge** request to Carol's exchange pointing Carol's exchange @@ -637,7 +652,7 @@ database.) -- CREATE TABLE IF NOT EXISTS partners (partner_serial_id BIGSERIAL UNIQUE - ,partner_master_pub BYTEA NOT NULL CHECK(LENGTH(reserve_pub)=32) + ,partner_master_pub BYTEA NOT NULL CHECK(LENGTH(partner_master_pub)=32) ,start_date INT8 NOT NULL ,end_date INT8 NOT NULL ,wad_frequency INT8 NOT NULL @@ -1057,7 +1072,7 @@ The overall changes required are not small: * New exchange logic required to make ``transfers`` requests for purses (another separate process). * New ``/account/$ACCOUNT_PUB/kyc`` endpoint required. -* New ``/purse/$PURSE_PUB/merge`` endpoint required. +* New ``/purses/$PURSE_PUB/merge`` endpoint required. * Additional tables to be verified by the auditor. * ``taler-exchange-wirewatch`` needs to support receiving purses closures and exchange-to-exchange wire transfers with WTIDs. diff --git a/design-documents/014-merchant-backoffice-ui.rst b/design-documents/014-merchant-backoffice-ui.rst @@ -1,12 +1,25 @@ DD 14: Merchant backoffice UI ############################# +:Design status: Accepted +:Implementation status: Implemented +:DD shepherd: TBD +:Historical contributors: Thien-Thi Nguyen, Christian Grothoff +:First published: 2021-01-30 +:Last substantive change: 2024-02-08 +:Implementation evidence: merchant (2021-08-05) +:Normative references: :doc:`../taler-merchant-manual`, :doc:`../core/api-merchant` + +.. note:: + + The user stories below record the original UI design. The current merchant + manual and API authentication specification are authoritative. Motivation ========== -The merchant should have a user-friendly way to manage the merchant -backend, which can currently only be done via a HTTP+JSON RESTful API +The merchant should have a user-friendly way to manage the merchant backend. +The implemented single-page application uses the HTTP+JSON RESTful API (:doc:`../core/api-merchant`). @@ -63,7 +76,7 @@ Story #1: Login Note: we have several authorization methods: - - HTTP ``Authorize`` header with pre-shared key + - HTTP ``Authorization`` header with a bearer token - (maybe?) username / password @@ -73,9 +86,9 @@ Story #1: Login different instances may use different credentials. So the SPA needs to fetch the list of instances. -3. Special case: If there are no instances, the ``default`` instance MUST +3. Special case: If there are no instances, the ``admin`` instance MUST be used, and the login should immediately move on to the ``setup`` - (default) instance dialog, forcing the user to setup the default + (admin) instance dialog, forcing the user to setup the admin instance upon first login. 4. After login, we (somehow) need to persist the login data in the SPA. @@ -100,7 +113,7 @@ Story #1: Login Story #2: Manage instances -------------------------- -This involves only the ``default`` instance owner. +This involves only the ``admin`` instance owner. Management operations include: @@ -114,10 +127,9 @@ Q: Do we have some separate "admin login" to manage instances? Who is actually allowed to manage instances? LibEuFin has some permissions system for this. -A: Default instance owner can manage instances. But, there is a -complication: *credentials* for all instances are managed in nginx -configuration, NOT via the REST API. So default instance owner can create -new instances, but access control MUST be configured by the sysadmin. +A: The admin instance owner can manage instances. Current authentication and +authorization, including scoped login tokens, is specified by the merchant +API. Story #3: View orders and their status, grant refunds diff --git a/design-documents/015-merchant-backoffice-routing.rst b/design-documents/015-merchant-backoffice-routing.rst @@ -1,6 +1,20 @@ DD 15: Merchant backoffice Routing ################################## +:Design status: Accepted +:Implementation status: Implemented +:DD shepherd: TBD +:Historical contributors: Sebastian +:First published: 2021-03-18 +:Last substantive change: 2021-08-06 +:Implementation evidence: merchant (2021-08-05) +:Normative references: :doc:`../taler-merchant-manual`, :doc:`../core/api-merchant` + +.. note:: + + This document records the original SPA routing and authentication design. + In particular, its ``default``-as-administrator convention is historical; + the current API uses the ``admin`` instance and scoped bearer tokens. Motivation ========== @@ -64,19 +78,19 @@ check for ``$BACKEND_URL/management/instances``: * if not found, then url should end with ``/instances/$INSTANCE``. otherwise is an error. app will continue as admin = false -* if ok then then $INSTANCE == 'default', app will continue as admin = true +* if ok then $INSTANCE == 'admin', app will continue as admin = true When a user access the SPA there are 3 scenarios possible: -* **standard**: admin is false so BACKEND_URL points to a non-default instance. +* **standard**: admin is false so BACKEND_URL points to a non-admin instance. standard features and links are shown -* **admin**: admin is true so BACKEND_URL point to default instance. same as +* **admin**: admin is true so BACKEND_URL points to the admin instance. As before and user can create and list instances with some additional links in the sidebar. * **mimic**: admin is true and the request parameter "instance" is set $INSTANCE - instance. BACKEND_URL point to default instance but the user is managing + instance. BACKEND_URL points to the admin instance but the user is managing $INSTANCE Normally all communication with the backend will be done to $BACKOFFICE_URL and @@ -114,7 +128,7 @@ Where admin or not, there is also this entry points: As an example: * ``$BACKOFFICE_URL/?instance=foo#/orders`` will show the orders of the foo - instance, assuming that BACKEND_URL points to the default instance. + instance, assuming that BACKEND_URL points to the admin instance. * ``$BACKOFFICE_URL/#/product/foo/update`` will show the update page for the ``foo`` product of the instance pointed by $BACKEND_URL @@ -148,10 +162,10 @@ Not found For any case that the backend respond 404 the application will render a custom not found page -Default instance is missing ---------------------------- +Admin instance is missing +------------------------- If the **user is admin** AND is loading the setting page (/update), product list (/products), order list (/orders) or transfer list (/transfers) AND **gets a -404** it will tell the user that it need to create a default instance before +404** it will tell the user that it needs to create an admin instance before proceeding. diff --git a/design-documents/016-backoffice-order-management.rst b/design-documents/016-backoffice-order-management.rst @@ -1,6 +1,20 @@ DD 16: Backoffice Order Management ################################## +:Design status: Accepted +:Implementation status: Implemented +:DD shepherd: TBD +:Historical contributors: Sebastian +:First published: 2021-03-19 +:Last substantive change: 2021-04-15 +:Implementation evidence: merchant (2021-08-05) +:Normative references: :doc:`../taler-merchant-manual`, :doc:`../core/api-merchant` + +.. note:: + + The screens below record the original UI design. The current merchant API + is authoritative for order fields and operations. + Summary ======= @@ -138,10 +152,6 @@ This section show optional values that can be overwritten by the merchant * ``max fee``: default value from the instance -* ``max wire fee``: default value from the instance - -* ``wire_fee_amortization``: default value from the instance - .. image:: ../images/backoffice-order-create.payment-section.svg :width: 800 @@ -248,9 +258,7 @@ collapsed as default. show disabled if unpaid * amount * fulfillment_url, if present * max fee -* max fire fee -* wire_fee_amortization -* list of (exchange | auditor) name and url +* list of exchange names and URLs * products table: list of products, one row per product * description diff --git a/design-documents/017-backoffice-inventory-management.rst b/design-documents/017-backoffice-inventory-management.rst @@ -1,6 +1,20 @@ DD 17: Backoffice Inventory Management ###################################### +:Design status: Accepted +:Implementation status: Implemented +:DD shepherd: TBD +:Historical contributors: Sebastian +:First published: 2021-03-19 +:Last substantive change: 2021-04-20 +:Implementation evidence: merchant (2020-05-02), taler-typescript-core (2026-08-06) +:Normative references: :doc:`../core/api-merchant`, :doc:`../taler-merchant-manual` + +.. note:: + + The screens below record the original UI design. The current merchant API + is authoritative for inventory fields and operations. + Summary ======= @@ -58,7 +72,7 @@ Create and Update Product form Update product will use the same form except for the ``product_id`` -* product_id: BACKOFFICE_URL + id +* product_id: a slug identifier * description: split in two fields, concatenated with a line separator * name: required, one line diff --git a/design-documents/018-contract-json.rst b/design-documents/018-contract-json.rst @@ -1,6 +1,15 @@ DD 18: Forgettable Data in JSON Contract Terms ############################################## +:Design status: Accepted +:Implementation status: Implemented +:DD shepherd: TBD +:Historical contributors: Florian Dold, Christian Grothoff +:First published: 2021-04-12 +:Last substantive change: 2021-05-09 +:Implementation evidence: exchange (2020-07-16), taler-typescript-core (2021-04-12) +:Normative references: :doc:`../core/api-merchant` + Summary ======= @@ -32,6 +41,14 @@ same before and after forgetting a forgettable part of the contract terms. Proposed Solution ================= +.. warning:: + + The algorithm below records the historical design. The normative contract + schema and forgetting behavior are specified by :doc:`../core/api-merchant`. + Implementations must follow that specification where it differs from this + rationale, including its treatment of ``$forgettable`` metadata and NUL + bytes; do not infer current behavior from the historical details below. + Members of objects can be marked as forgettable by adding metadata to the contract terms JSON. Before hashing the contract terms JSON, it is first scrubbed and canonicalized. Scrubbing replaces forgettable members with a @@ -88,7 +105,7 @@ Forgetting a Forgettable Member To forget a forgettable member, it is removed from the parent object, and the salted hash of the member's -scrubbed and canonicalized value is put into the special ``$forgotten$`` +scrubbed and canonicalized value is put into the special ``$forgotten`` member of the parent object. @@ -158,12 +175,12 @@ a minimal interoperability test: { "k1": 1, - "_forgettable": { + "$forgettable": { "k1": "SALT" }, "k2": { "n1": true, - "_forgettable": { + "$forgettable": { "n1": "salt" } }, @@ -174,7 +191,7 @@ a minimal interoperability test: Hashing the above contract results in the following Crockford base32 encoded hash -``287VXK8T6PXKD05W8Y94QJNEFCMRXBC9S7KNKTWGH2G2J2D7RYKPSHNH1HG9NT1K2HRHGC67W6QM6GEC4BSN1DPNEBCS0AVDT2DBP5G``. +``VDE8JPX0AEEE3EX1K8E11RYEWSZQKGGZCV6BWTE4ST1C8711P7H850Z7F2Q2HSSYETX87ERC2JNHWB7GTDWTDWMM716VKPSRBXD7SRR``. Note that typically the salt values must be chosen at random, only for this test we use static salt values. diff --git a/design-documents/019-wallet-backup-merge.rst b/design-documents/019-wallet-backup-merge.rst @@ -1,11 +1,21 @@ XX 19: Wallet Backup Merging ############################ +:Design status: Superseded +:Implementation status: Prototype +:DD shepherd: TBD +:Historical contributors: Florian Dold, Christian Grothoff, Iván Ávalos +:First published: 2021-04-26 +:Last substantive change: 2026-08-09 +:Superseded by: :doc:`092-incremental-backup-sync` + .. warning:: This design document is deprecated. The incremental backup and sync protocol described in `DD 92`_ supersedes it. + The body below is retained for historical context and is non-normative. + .. _DD 92: https://docs.taler.net/design-documents/092-incremental-backup-sync.html Summary diff --git a/design-documents/020-backoffice-rewards-management.rst b/design-documents/020-backoffice-rewards-management.rst @@ -1,6 +1,19 @@ XX 20: Backoffice Rewards Management #################################### +:Design status: Accepted +:Implementation status: Removed +:DD shepherd: TBD +:Historical contributors: Sebastian, Christian Grothoff +:First published: 2021-05-13 +:Last substantive change: 2024-02-08 +:Implementation evidence: merchant (2024-02-05, 2024-02-09), taler-typescript-core (2024-02-07, 2024-03-07) + +.. warning:: + + Reward and reserve management APIs were removed in 2024. The body below is + retained for historical context and is non-normative. + Summary ======= diff --git a/design-documents/021-exchange-key-continuity.rst b/design-documents/021-exchange-key-continuity.rst @@ -1,6 +1,21 @@ DD 21: Exchange Key Continuity ############################## +:Design status: Accepted +:Implementation status: Partial +:DD shepherd: TBD +:Historical contributors: Florian Dold +:First published: 2021-05-25 +:Last substantive change: 2021-05-25 +:Implementation evidence: taler-typescript-core (2024-01-16) +:Normative references: :doc:`048-wallet-exchange-lifecycle`, :doc:`065-exchange-base-url-migration`, :doc:`../wallet/wallet-core` + +.. warning:: + + The direct-trust/auditor model in this document is historical, and wallets + now support controlled exchange base-URL migration as specified in DD65. + Those parts of the body are non-normative. + Summary ======= @@ -31,8 +46,8 @@ should still be handled gracefully. Wallet ------ -We generally assume that the base URL of an exchange stays constant. -Wallets do not support changing the base URL of an exchange. +We generally assume that the base URL of an exchange stays constant. Wallets +support controlled base-URL migration as specified in DD65. A ``/keys`` response with an unknown exchange master public key is only accepted if the exchange is audited by a trusted auditor or the wallet diff --git a/design-documents/022-wallet-auditor-reports.rst b/design-documents/022-wallet-auditor-reports.rst @@ -1,9 +1,19 @@ DD 22: Wallet Proofs to Auditor ############################### +:Design status: Draft +:Implementation status: Not started +:DD shepherd: TBD +:Historical contributors: Florian Dold +:First published: 2021-09-12 +:Last substantive change: 2021-09-12 +:Normative references: :doc:`../core/api-auditor` + .. note:: - Status (2021-05-25): Writing in progress. + This incomplete proposal is retained for historical context and is + non-normative. Auditor complaint submission remains to be designed and + implemented in the normative API. Summary diff --git a/design-documents/023-taler-kyc.rst b/design-documents/023-taler-kyc.rst @@ -1,6 +1,20 @@ DD 23: Taler KYC ################ +:Design status: Accepted +:Implementation status: Implemented +:DD shepherd: TBD +:Historical contributors: Florian Dold, Christian Grothoff, Özgür Kesim +:First published: 2021-09-12 +:Last substantive change: 2026-05-03 +:Implementation evidence: exchange (2024-04-22) +:Normative references: :doc:`../core/api-exchange`, :doc:`../taler-kyc-manual` + +.. note:: + + This is a living design rationale. The core exchange API and KYC manual + are authoritative for implemented endpoints and operations. + Summary ======= @@ -149,8 +163,13 @@ be tracked in the system statistics: * sanction list import / update -TODO: Sanction lists -^^^^^^^^^^^^^^^^^^^^ +Sanction lists +^^^^^^^^^^^^^^ + +.. note:: + + The implementation described in the current KYC manual supersedes this + historical design sketch. We need to be able to import new sanction lists (whenever they are published) and then check existing AMLA files against those lists. Additionally, newly @@ -894,6 +913,11 @@ New endpoints Modifications to existing endpoints ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +.. note:: + + This subsection describes an earlier KYC API design. The core exchange API + and KYC manual supersede its endpoint names and processing model. + When withdrawing, the exchange checks if the KYC status is acceptable. If no KYC was done and if either the amount withdrawn over a particular timeframe exceeds the threshold or the reserve received a P2P transfer, then a @@ -902,7 +926,7 @@ to the new ``/kyc-check/`` handler. When depositing, the exchange aggregator (!) checks the KYC status and if negative, returns an additional information field via the -``aggregation_transient`` table which is returned via GET ``/deposts/`` to the +``aggregation_transient`` table which is returned via GET ``/deposits/`` to the merchant. When merging into a reserve, the KYC status is checked and again the diff --git a/design-documents/024-age-restriction.rst b/design-documents/024-age-restriction.rst @@ -1,6 +1,21 @@ DD 24: Anonymous Age Restriction Extension ########################################## +:Design status: Accepted +:Implementation status: Implemented +:DD shepherd: TBD +:Historical contributors: Özgür Kesim, Christian Grothoff, Florian Dold +:First published: 2021-10-12 +:Last substantive change: 2025-12-16 +:Implementation evidence: exchange (2022-03-01, 2022-03-28), taler-typescript-core (2022-04-19) +:Normative references: :doc:`../core/api-exchange` + +.. note:: + + Age restriction remains implemented. The generic pluggable extension + mechanism from DD06 has been retired; current exchange API documentation is + authoritative for how age-restricted denominations are advertised and used. + Summary ======= @@ -109,9 +124,8 @@ The main ideas are as follows: Merchant. -TODO: Summarize the design based on the five functions ``Commit()``, -``Attest()``, ``Verify()``, ``Derive()``, ``Compare()``, once the paper from -Özgür and Christian is published. +The five-function design based on ``Commit()``, ``Attest()``, ``Verify()``, +``Derive()`` and ``Compare()`` is described in the paper referenced below. Changes in the Exchange API ^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -128,8 +142,9 @@ Extension for age restriction .. note:: - Registering an extension is defined in - :doc:`design document 006 ― Extensions <006-extensions>`. + This subsection records the original integration with DD06. The generic + extension registration mechanism has since been retired; the current + ``/keys`` schema is authoritative for age-restriction advertisement. The exchange indicates support for age-restriction in response to ``/keys`` by diff --git a/design-documents/025-withdraw-from-wallet.rst b/design-documents/025-withdraw-from-wallet.rst @@ -1,6 +1,20 @@ DD 25: Withdraw coins manually starting from the wallet ####################################################### +:Design status: Accepted +:Implementation status: Implemented +:DD shepherd: TBD +:Historical contributors: Sebastian +:First published: 2021-10-14 +:Last substantive change: 2021-10-14 +:Implementation evidence: taler-typescript-core (2020-06-21), taler-android (2021-12-07) +:Normative references: :doc:`../wallet/wallet-core`, :doc:`048-wallet-exchange-lifecycle` + +.. note:: + + The screens below record the original UI design. The wallet API and DD48 + are authoritative for manual withdrawal and exchange lifecycle behavior. + Summary ======= diff --git a/design-documents/026-refund-fees.rst b/design-documents/026-refund-fees.rst @@ -1,6 +1,15 @@ DD 26: Refunds and Fees ####################### +:Design status: Accepted +:Implementation status: Implemented +:DD shepherd: TBD +:Historical contributors: Christian Grothoff, Florian Dold +:First published: 2021-12-07 +:Last substantive change: 2023-09-15 +:Implementation evidence: merchant (2022-07-09) +:Normative references: :doc:`../core/api-exchange` + .. note:: This is implemented (as of 2023-09-15). diff --git a/design-documents/027-sandboxing-taler.rst b/design-documents/027-sandboxing-taler.rst @@ -1,10 +1,17 @@ DD 27: Sandboxing all the Taler services ######################################## +:Design status: Abandoned +:Implementation status: Not started +:DD shepherd: TBD +:Historical contributors: Marcello Stanisci, Florian Dold +:First published: 2022-02-07 +:Last substantive change: 2022-02-10 + .. note:: - This design document is currently a draft, it - does not reflect any implementation decisions yet. + This proposal was abandoned and does not reflect implementation decisions. + The body below is retained for historical context and is non-normative. Summary ======= diff --git a/design-documents/028-deposit-policies.rst b/design-documents/028-deposit-policies.rst @@ -1,9 +1,19 @@ DD 28: Deposit Policy Extensions ################################ -.. note:: +:Design status: Accepted +:Implementation status: Removed +:DD shepherd: TBD +:Historical contributors: Özgür Kesim +:First published: 2022-10-07 +:Last substantive change: 2023-12-07 +:Implementation evidence: exchange (2022-11-04, 2026-05-31) - This is Work-In-Progress. +.. warning:: + + Deposit policy extensions were prototyped and subsequently removed together + with the generic extension mechanism in 2026. The body below is retained + for historical context and is non-normative. Summary ******* @@ -167,7 +177,7 @@ Invariants The following invariants need to be fulfilled and be checked by the auditor: - The fulfillment state of a policy is **Insufficient** IF AND ONLY IF the - amount in ``policy_details.commitment`` is equal or larger than the amount in + amount in ``policy_details.commitment`` is strictly larger than the amount in ``policy_details.accumulated_total``. - The sum of amounts in ``policy_details.fee`` and diff --git a/design-documents/029-mobile-ui.rst b/design-documents/029-mobile-ui.rst @@ -1,6 +1,18 @@ DD 29: Mobile P2P UI #################### +:Design status: Abandoned +:Implementation status: Not started +:DD shepherd: TBD +:Historical contributors: Sebastian +:First published: 2022-06-16 +:Last substantive change: 2022-06-16 + +.. note:: + + This incomplete UI sketch was abandoned. The body below is retained for + historical context and is non-normative. + Summary ======= diff --git a/design-documents/030-offline-payments.rst b/design-documents/030-offline-payments.rst @@ -1,6 +1,18 @@ DD 30: Offline payments ####################### +:Design status: Abandoned +:Implementation status: Not started +:DD shepherd: TBD +:Historical contributors: Florian Dold +:First published: 2022-08-04 +:Last substantive change: 2022-08-04 + +.. note:: + + This exploratory proposal was abandoned. The body below is retained for + historical context and is non-normative. + Summary ======= diff --git a/design-documents/031-invoicing.rst b/design-documents/031-invoicing.rst @@ -1,6 +1,20 @@ DD 31: Invoicing ################ +:Design status: Accepted +:Implementation status: Implemented +:DD shepherd: TBD +:Historical contributors: Christian Grothoff +:First published: 2022-08-20 +:Last substantive change: 2024-02-08 +:Implementation evidence: exchange (2022-09-18, 2022-09-27, 2022-10-09) +:Normative references: :doc:`../core/api-exchange` + +.. note:: + + The current exchange API is authoritative for the implemented reserve + open, attestation and close operations. + Summary ======= @@ -91,7 +105,7 @@ Specifically, the solution involves three new endpoints: Opening reserves ---------------- - * This new endpoint ``/reserve/$RID/open`` allows the user to + * This new endpoint ``/reserves/$RID/open`` allows the user to pay (for a year) to create a fixed number of purses and to keep the reserve ``open`` (preventing auto-close); the endpoint typically triggers a first (balance-independent) @@ -112,7 +126,7 @@ Opening reserves Reserve Attestation ------------------- - * This new endpoint ``/reserve/$RID/attest`` allows the user to + * This new endpoint ``/reserves/$RID/attest`` allows the user to obtain exchange-signed KYC information about themselves. This will basically be a list of (GANA standardized) attributes and exchange signatures. The user can then choose which of @@ -138,7 +152,7 @@ Reserve Attestation Closing reserves ---------------- - * This new endpoint ``/reserve/$RID/close`` allows the user to + * This new endpoint ``/reserves/$RID/close`` allows the user to force-close a reserve that has not yet expired. This is useful in case invoices have been paid into the reserve and the user wants to get their money out. The ``close`` endpoint diff --git a/design-documents/032-brandt-vickrey-auctions.rst b/design-documents/032-brandt-vickrey-auctions.rst @@ -1,6 +1,19 @@ DD 32: Brandt-Vickrey Auctions ############################## +:Design status: Abandoned +:Implementation status: Not started +:DD shepherd: TBD +:Historical contributors: Christian Grothoff, Özgür Kesim +:First published: 2022-08-21 +:Last substantive change: 2022-10-16 + +.. warning:: + + This proposal was not implemented. It depends on the deposit-policy and + generic extension mechanisms, which were subsequently removed. The body + below is retained for historical context and is non-normative. + Summary ======= diff --git a/design-documents/033-database.rst b/design-documents/033-database.rst @@ -1,6 +1,21 @@ DD 33: Database Schema and Versioning ##################################### +:Design status: Accepted +:Implementation status: Implemented +:DD shepherd: TBD +:Historical contributors: Christian Grothoff +:First published: 2022-11-30 +:Last substantive change: 2022-11-30 +:Implementation evidence: exchange (2022-11-24), merchant (2024-01-07, 2024-01-10) +:Normative references: :ref:`DatabaseVersioning`, :ref:`MerchantDatabaseScheme` + +.. note:: + + This document records the shared versioning design. Current database + migration files and stored procedures are authoritative for implementation + details. + Summary ======= @@ -111,11 +126,11 @@ procedures to support operations on shards. Merchant details ^^^^^^^^^^^^^^^^ -The merchant does not (yet) need any type of master table, as we do not -(yet) use any kind of sharding or partitioning. There are also no -stored procedures being used by the backend. Hence, it is simply the -"versioning.sql"-controlled table creation/alteration sequence -(merchant-0001.sql, etc.) and the "drop.sql" to reset everything. +The merchant does not currently use the exchange's master-table scheme for +sharding or partitioning. Its schema is managed by the +``versioning.sql``-controlled table creation and alteration sequence and its +generated ``procedures.sql``. The backend now uses stored functions and +procedures in addition to versioned table migrations. Alternatives diff --git a/design-documents/034-wallet-db-migration.rst b/design-documents/034-wallet-db-migration.rst @@ -1,6 +1,21 @@ DD 34: Considerations for Wallet Database Migrations #################################################### +:Design status: Accepted +:Implementation status: Implemented +:DD shepherd: TBD +:Historical contributors: Florian Dold +:First published: 2023-01-27 +:Last substantive change: 2023-01-27 +:Implementation evidence: taler-typescript-core (2023-07-11, 2026-07-19, 2026-08-06) +:Normative references: :doc:`../developer/taler-wallet-developer` + +.. note:: + + The wallet now has both IndexedDB and native SQLite database backends. The + The wallet developer manual describes the migration contract; current + wallet source is authoritative for backend-specific implementation details. + Summary ======= @@ -16,22 +31,26 @@ Requirements ============ * Migrations may not result in data loss and must be automatic. -* Our schema migration must be compatible with how IndexedDB works. This means that we can't - do arbitrary schema migrations at any time, but need to increment the IndexedDB database version - every time we add/remove/change an object store or index. +* Migrations of the IndexedDB backend must be compatible with how IndexedDB + works. This means that we cannot do arbitrary schema migrations at any time, + but need to increment the IndexedDB database version every time we add, + remove or change an object store or index. The native SQLite backend has a + separate versioned migration mechanism. Proposed Solution ================= -The schema of the wallet database is described in code in -https://git.taler.net/wallet-core.git/tree/packages/taler-wallet-core/src/db.ts#n1959 -(``walletStoresV1``). This schema description is used to initialize and upgrade the -database automatically. +The IndexedDB schema of the wallet database is described in +https://git.taler.net/wallet-core.git/tree/packages/taler-wallet-core/src/db/indexeddb/schema.ts. +The native SQLite schema is described separately in +https://git.taler.net/wallet-core.git/tree/packages/taler-wallet-core/src/db/sqlite/schema.ts. +These schema descriptions are used to initialize and upgrade their respective +databases automatically. In IndexedDB terminology, the wallet has two databases: 1. The ``"taler-wallet-meta"`` stores metadata about the current major-version database -2. The major-version database (currently ``"taler-wallet-main-v9"`` stores the +2. The major-version database (currently ``"taler-wallet-main-v10"``) stores the actual data of the wallet. This indirection allows major database migrations to be safe despite the @@ -40,11 +59,11 @@ migration is very limited. By migrating to a completely new database, we can keep around the old database until we're sure that the migration has succeeded and, if required, push new code to fix migration errors. -We have three different mechanisms to introduce changes to the database: +The IndexedDB backend has three mechanisms to introduce changes: 1. Major migrations. These migrations introduce a new major-version database and must manually - migrate the data from the previons major-version database. This migration should be - added in ``db.ts#openTalerDatabase``. + migrate the data from the previous major-version database. This migration should be + added in ``db/indexeddb/database.ts#openTalerDatabase``. Major migrations should be used **very** seldomly. It can make sense to implement them as a backup cycle, i.e. implement a backup export from the old version, upgrade to the latest backup version and then re-import into the new major-version database. @@ -57,7 +76,11 @@ We have three different mechanisms to introduce changes to the database: when a new mandatory field is added to an existing object store or some data format changes. Fixups are also useful to retroactively fix bugs introduced by previously deployed wallet versions. - They must be added to ``db.ts#walletDbFixups`` + They must be added to ``db/indexeddb/fixups.ts#walletDbFixups``. + +The native SQLite backend uses ordered schema migrations in +``db/sqlite/schema.ts``. Migration from the IndexedDB emulation to the native +schema is implemented separately in ``db/migration/native.ts``. Alternatives ============ diff --git a/design-documents/035-regional-currencies.rst b/design-documents/035-regional-currencies.rst @@ -1,6 +1,15 @@ DD 35: Regional currencies ########################## +:Design status: Accepted +:Implementation status: Partial +:DD shepherd: TBD +:Historical contributors: Florian Dold, Sebastian +:First published: 2023-02-06 +:Last substantive change: 2024-02-06 +:Implementation evidence: taler-typescript-core (2023-02-12), taler-android (2023-11-29), taler-ios (2024-02-10) +:Normative references: ``wallet/wallet-core.md`` + Summary ======= diff --git a/design-documents/036-currency-conversion-service.rst b/design-documents/036-currency-conversion-service.rst @@ -1,6 +1,15 @@ DD 36: Currency conversion service ################################## +:Design status: Accepted +:Implementation status: Partial +:DD shepherd: TBD +:Historical contributors: Marcello Stanisci, Özgür Kesim, Antoine A, Christian Grothoff +:First published: 2023-02-13 +:Last substantive change: 2023-12-15 +:Implementation evidence: taler-android (2023-12-05) +:Normative references: ``core/api-corebank.rst``, ``core/api-bank-conversion-info.rst`` + Summary ======= @@ -71,14 +80,14 @@ Libeufin-bank learns instantly about a cash-out operation, because it's *the* service offering such feature. Therefore, as soon as a cash-out operation gets TAN-confirmed, libeufin-bank performs a wire transfer from regio-user to regio-issuer by specifying the amount without any rates/fees -applied. Along the same database transaction, a SQL trigger store the -*instructions* of another payment *P* from fiat-issuer to fiat-target, +applied. Along the same database transaction, a SQL trigger stores the +*instructions* of another payment *Q* from fiat-issuer to fiat-target, but this time **with** the cash-out rates/fees. -Asynchronously, a libeufin-nexus background task picks P and sends it to -the fiat bank. Finally, fiat bank conducts P and fiat-target receives the +Asynchronously, a libeufin-nexus background task picks Q and sends it to +the fiat bank. Finally, fiat bank conducts Q and fiat-target receives the wanted amount. The same libeufin-nexus background task should also retry -previous payments like P that failed to be submitted to fiat bank. +previous payments like Q that failed to be submitted to fiat bank. Cash-in operation ----------------- diff --git a/design-documents/037-wallet-transactions-lifecycle.rst b/design-documents/037-wallet-transactions-lifecycle.rst @@ -1,6 +1,15 @@ DD 37: Wallet Transaction Lifecycle ################################### +:Design status: Accepted +:Implementation status: Implemented +:DD shepherd: TBD +:Historical contributors: Sebastian, Özgür Kesim, Christian Grothoff, Florian Dold +:First published: 2023-02-13 +:Last substantive change: 2026-02-17 +:Implementation evidence: taler-typescript-core (2023-04-22), taler-android (2023-05-15) +:Normative references: ``wallet/wallet-core.md`` + .. contents:: Table of Contents :depth: 2 @@ -958,7 +967,7 @@ Transaction Type: Peer Pull Debit We have downloaded information about the pull payment and are waiting for the user to confirm. - * ``[action:confirm-pay] => pending(submit-payment)`` + * ``[action:confirm-pay] => pending(deposit)`` * ``[action:delete] => deleted`` * ``[timeout] => aborted`` @@ -970,7 +979,6 @@ Transaction Type: Peer Pull Debit * ``[action:suspend] => suspended(deposit)`` * ``[processed-success] => done`` * ``[failure:timeout] => aborting(refresh)`` - * ``[processed-success] => done`` * ``[failure:other] => aborting(refund)`` * ``suspended(deposit)`` @@ -978,7 +986,7 @@ Transaction Type: Peer Pull Debit User suspended depositing into the purse. * ``[action:resume] => pending(deposit)`` - * ``[action:abort] => aborting_refund`` + * ``[action:abort] => aborting(refund)`` * ``aborting(refund)`` diff --git a/design-documents/038-demobanks-protocol-suppliers.rst b/design-documents/038-demobanks-protocol-suppliers.rst @@ -1,6 +1,19 @@ -XX 38: Demobanks protocol suppliers +DD 38: Demobanks protocol suppliers ################################### +:Design status: Abandoned +:Implementation status: Not started +:DD shepherd: TBD +:Historical contributors: Marcello Stanisci, Özgür Kesim, Florian Dold, Christian Grothoff +:First published: 2023-03-15 +:Last substantive change: 2023-03-21 + +.. warning:: + + This is an abandoned historical design. The terminology and LibEuFin + Sandbox architecture described below are not normative for current + implementations. + Summary ======= @@ -58,7 +71,7 @@ is therefore a 'static protocol supplier' with static demobank. in a demobank whose name appear in the URI is as well a 'static protocol supplier' with dynamic demobank. -Note: the upcoming (in version 0.9.3) JSON-based supplier that will +Historical note: the JSON-based supplier that was planned for version 0.9.3 let Nexus reach Sandbox accounts is planned as a 'dynamic protocol supplier' with dynamic demobank. That allows Taler demos to only speak JSON. diff --git a/design-documents/039-taler-browser-integration.rst b/design-documents/039-taler-browser-integration.rst @@ -1,6 +1,27 @@ DD 39: Taler Wallet Browser Integration Considerations ###################################################### +:Design status: Accepted +:Implementation status: Implemented +:DD shepherd: TBD +:Historical contributors: Sebastian, Christian Grothoff, Florian Dold +:First published: 2023-03-22 +:Last substantive change: 2025-11-25 +:Implementation evidence: taler-typescript-core (2026-08-13) +:Normative references: :doc:`../wallet/browser-integration` +:Upstream follow-up: The ``wallet-webui`` browser-integration manual currently + presents implementation-only helpers as part of a public shape; align it + with the normative wallet manual, which defines no supported callable + ``window.taler`` methods. + +.. note:: + + The implemented integration is preference-gated and does not expose public + callable methods on ``window.taler``. New websites should advertise + actions with ``taler-uri`` and request ``uri`` and/or ``callback`` support. + Details below about programmatic invocation, handler replacement, and a + later ``present: false`` callback are historical design considerations. + Summary ======= @@ -93,7 +114,7 @@ are provided: 2. Overriding ``<a href="taler://..." onclick=...>`` tags to trigger the wallet. The onclick handler (which must call preventDefault) can implement behavior that happens only when the webextension is not available. -3. Future (possibly post-1.0): A ``window.taler`` JavaScript API that is injected +3. A ``window.taler`` JavaScript API that is injected into every page that requests it via a meta tag. This is useful for SPAs that want to programmatically trigger the Taler wallet. @@ -127,7 +148,7 @@ The following features are supported: of the extension, the callback will be called with ``present: false`` on a best-effort basis. Websites **MUST NOT** rely the ``present: false`` callback to be fired. -* (future): ``api`` will inject the ``window.taler`` API into the page. +* ``api`` injects the ``window.taler`` API into the page. It is recommended to use the ``callback`` feature to wait until the ``window.taler`` object is available, as it is provided asynchronously by the extension. diff --git a/design-documents/040-distro-packaging.rst b/design-documents/040-distro-packaging.rst @@ -1,10 +1,19 @@ DD 40: Distro Packaging ####################### -.. admonition:: Metadata +:Design status: Proposed +:Implementation status: Partial +:DD shepherd: TBD +:Historical contributors: Florian Dold +:First published: 2023-03-28 +:Last substantive change: 2023-03-28 +:Implementation evidence: merchant (2023-08-04) - Status - proposed +.. note:: + + Adoption of these packaging guidelines is incomplete. In particular, + package-local documentation and packaging scripts may still diverge from + the policy below. Summary ======= @@ -121,9 +130,9 @@ components that do not support DB connections via unix domain sockets. Definition of Done ================== -* All Taler and Anastasis packages follow the guidelines from this DD -* Packages installation has been manually tested -* Automated setup scripts (``deployment.git``) have been adjusted to use the +* [ ] all Taler and Anastasis packages follow the guidelines from this DD +* [ ] package installation has been manually tested across supported packages +* [ ] automated setup scripts (``deployment.git``) have been adjusted to use the configuration file templates shipped in the package, instead of using their own config templates. diff --git a/design-documents/041-wallet-balance-amount-definitions.rst b/design-documents/041-wallet-balance-amount-definitions.rst @@ -1,6 +1,14 @@ DD 41: Wallet Balance and Amount Definitions ############################################ +:Design status: Draft +:Implementation status: Partial +:DD shepherd: TBD +:Historical contributors: Sebastian, Christian Grothoff, Florian Dold, Marc Stibane +:First published: 2023-03-30 +:Last substantive change: 2024-09-12 +:Normative references: ``wallet/wallet-core.md`` + Summary ======= diff --git a/design-documents/042-synthetic-wallet-errors.rst b/design-documents/042-synthetic-wallet-errors.rst @@ -1,6 +1,15 @@ DD 42: Wallet Dev Experiments ############################# +:Design status: Accepted +:Implementation status: Implemented +:DD shepherd: TBD +:Historical contributors: Florian Dold +:First published: 2023-03-28 +:Last substantive change: 2023-04-21 +:Implementation evidence: taler-typescript-core (2022-10-12) +:Normative references: ``developer/taler-wallet-developer.rst`` + Summary ======= diff --git a/design-documents/043-managing-prebuilt-artifacts.rst b/design-documents/043-managing-prebuilt-artifacts.rst @@ -1,6 +1,14 @@ DD 43: Managing Prebuilt Artifacts and Source-Level Dependencies ################################################################ +:Design status: Accepted +:Implementation status: N/A +:DD shepherd: TBD +:Historical contributors: Florian Dold +:First published: 2023-05-04 +:Last substantive change: 2025-11-26 +:Normative references: :doc:`../developer/taler-developer-manual` + .. note:: History: diff --git a/design-documents/044-ci-system.rst b/design-documents/044-ci-system.rst @@ -1,6 +1,20 @@ DD 44: CI System ################ +:Design status: Accepted +:Implementation status: Implemented +:DD shepherd: TBD +:Historical contributors: Özgür Kesim, Devan Carpenter, Christian Grothoff +:First published: 2023-07-13 +:Last substantive change: 2023-12-17 +:Implementation evidence: exchange (2023-10-05), merchant (2023-10-12), taler-typescript-core (2024-01-15), libeufin (2024-02-18) +:Normative references: :doc:`../developer/taler-developer-manual` + +.. note:: + + Repository-local CI definitions are the current operational source of + truth. Cross-project builder triggering remains unspecified below. + Summary ======= diff --git a/design-documents/045-kyc-inheritance.rst b/design-documents/045-kyc-inheritance.rst @@ -1,6 +1,18 @@ DD 45: Single-Depth Inheritance of KYC for Reserves ################################################### +:Design status: Abandoned +:Implementation status: Not started +:DD shepherd: TBD +:Historical contributors: Özgür Kesim +:First published: 2023-07-30 +:Last substantive change: 2023-07-31 + +.. warning:: + + This is an abandoned historical design. It was not integrated into the + current protocol specifications and must not be treated as normative. + Summary ======= @@ -154,11 +166,9 @@ TODO. Definition of Done ================== -For the exchange, the implementation of the configuration option and the -endpoint, and corresponding unit tests in ``src/testing`` are necessary. - - -For the wallet: TODO. +* [ ] exchange configuration option and endpoint implemented +* [ ] exchange unit tests added in ``src/testing`` +* [ ] wallet support implemented Alternatives ============ diff --git a/design-documents/046-mumimo-contracts.rst b/design-documents/046-mumimo-contracts.rst @@ -1,6 +1,20 @@ DD 46: Contract Format v1 ######################### +:Design status: Accepted +:Implementation status: Partial +:DD shepherd: TBD +:Historical contributors: Christian Blättler, Stefan Kügel, Florian Dold, Christian Grothoff +:First published: 2023-08-11 +:Last substantive change: 2026-08-04 +:Implementation evidence: merchant (2025-03-05), taler-typescript-core (2026-07-06) +:Normative references: ``core/api-merchant.rst``, ``wallet/wallet-core.md`` + +.. note:: + + The REST API specifications are normative for the implemented wire format. + Future-work and rationale sections in this DD do not extend those APIs. + Summary ======= @@ -643,23 +657,23 @@ period. Definition of Done ================== - - Merchant backend support for multiple currencies - - Merchant backend support for consuming and issuing tokens - - Merchant SPA support for configuring new tokens of different types - - Wallet-core support for various new contract types - - Wallet-core filters for feasible contracts and possibly auto-executes subscriptions - - Wallet-GUIs (WebEx, Android, iOS) render new contract types - - Wallet-GUIs (WebEx, Android, iOS) allow user to select between multiple contracts - - Documentation for developers is up-to-date - - Token anonymity set size (ASS) authority implemented, documented - - Merchants report anonymity set size increases to ASS authority - - Wallets process anonymity set size reports from ASS authority - - Bachelor thesis written on applications and design - - Academic paper written on DONAU (requirements, design, implementation) - - DONAU implemented, documented - - DONAU receipt validation application implemented - - Integration tests exist in wallet-core - - Deliverables accepted by EC + - [ ] Merchant backend support for multiple currencies + - [x] Merchant backend support for consuming and issuing tokens + - [ ] Merchant SPA support for configuring new tokens of different types + - [x] Wallet-core support for contract format v1 + - [ ] Wallet-core filters for feasible contracts and automatic subscription execution + - [ ] Wallet-GUIs (WebEx, Android, iOS) render all new contract types + - [ ] Wallet-GUIs (WebEx, Android, iOS) allow users to select between multiple contracts + - [x] Implemented wire formats documented in the normative API specifications + - [ ] Token anonymity set size (ASS) authority implemented and documented + - [ ] Merchants report anonymity set size increases to ASS authority + - [ ] Wallets process anonymity set size reports from ASS authority + - [x] Bachelor thesis written on applications and design + - [x] Academic paper written on DONAU (requirements, design, implementation) + - [x] DONAU implemented and documented + - [ ] DONAU receipt-validation application completed + - [x] Integration tests exist in wallet-core + - [ ] Deliverables accepted by EC While rationing is part of the design, we expect the actual implementation to be done much later and thus should not consider it part of the "DONE" part. diff --git a/design-documents/047-stefan.rst b/design-documents/047-stefan.rst @@ -1,6 +1,15 @@ DD 47: STEFAN ############# +:Design status: Accepted +:Implementation status: Partial +:DD shepherd: TBD +:Historical contributors: Christian Grothoff, Florian Dold +:First published: 2023-08-11 +:Last substantive change: 2023-08-24 +:Implementation evidence: exchange (2023-08-11), merchant (2023-08-24) +:Normative references: ``core/exchange/get-keys.rst``, ``manpages/taler-exchange.conf.5.rst`` + Summary ======= @@ -145,12 +154,12 @@ do their own internal actual coin selection to minimize fees. Definition of Done ================== - - exchange modified (DONE) - - merchant understands STEFAN curve in backend (DONE) - - merchant SPA has configuration option to enable use of STEFAN-curves - - wallet-core uses STEFAN-curves to compute display fees - - wallet-core supports annual reconcilliation transaction - - wallet GUIs use STEFAN-curves when comparing exchange fee structures + - [x] exchange modified + - [x] merchant understands STEFAN curve in backend + - [ ] merchant SPA has configuration option to enable use of STEFAN-curves + - [ ] wallet-core uses STEFAN-curves to compute display fees + - [ ] wallet-core supports annual reconcilliation transaction + - [ ] wallet GUIs use STEFAN-curves when comparing exchange fee structures Alternatives diff --git a/design-documents/048-wallet-exchange-lifecycle.rst b/design-documents/048-wallet-exchange-lifecycle.rst @@ -1,6 +1,16 @@ DD 48: Wallet Exchange Lifecycle and Management ############################################### +:Design status: Accepted +:Implementation status: Implemented +:DD shepherd: TBD +:Historical contributors: Marc Stibane, Sebastian, Florian Dold, Christian Grothoff +:First published: 2023-08-22 +:Last substantive change: 2025-07-03 +:Implementation evidence: taler-typescript-core (2023-08-30), taler-android (2024-01-30) +:Normative references: ``wallet/wallet-core.md`` +:Upstream follow-up: Regenerate ``wallet/wallet-core.md`` from current taler-typescript-core; the checked-in output has a stale ``DeleteExchangeOp`` discriminator and comment. + Summary ======= @@ -10,9 +20,10 @@ of exchanges in the wallet. Motivation ========== -The current wallet implementation lacks requests to manage exchanges. -It also always fetches the /keys info of all exchanges, because it doens't -distinguish between used and preset/added exchanges. +At the time this design was written, the wallet implementation lacked requests +to manage exchanges and always fetched the ``/keys`` information of all +exchanges because it did not distinguish between used and preset/added +exchanges. The current wallet API implements exchange-management requests. Requirements ============ @@ -131,11 +142,11 @@ for ``/terms``, so that the wallet can already download the full response (not j Definition of Done ================== - * states implemented in wallet-core - * exchange management specified on a UI level - * webex implemented - * android wallet implemented - * ios wallet implemented + * [x] states implemented in wallet-core + * [x] exchange management specified on a UI level + * [ ] WebExtension implementation verified against the full DD + * [x] Android wallet exchange deletion implemented + * [ ] iOS wallet implementation verified against the full DD Discussion / Q&A ================ @@ -146,4 +157,3 @@ Discussion / Q&A exchange might *permanently* brick users' wallets. The wallet should always re-try contacting the exchange and of course possibly report information to the auditor. - diff --git a/design-documents/049-auth.rst b/design-documents/049-auth.rst @@ -1,6 +1,20 @@ DD 49: Authentication ##################### +:Design status: Accepted +:Implementation status: Implemented +:DD shepherd: TBD +:Historical contributors: Florian Dold, Sebastian, Antoine A, Martin Schanzenbach, Christian Grothoff +:First published: 2023-09-06 +:Last substantive change: 2025-06-19 +:Implementation evidence: merchant (2023-09-06), libeufin (2024-11-15) +:Normative references: ``core/api-merchant.rst``, ``core/api-corebank.rst`` + +.. note:: + + Authentication is implemented, but token-refresh syntax is + component-specific. The component API specifications are normative. + Summary ======= @@ -196,18 +210,20 @@ through configuration files and/or default scopes overridden. Token refresh ============= -Tokens may be requested to be refreshable. -In older API versions this was achieved by setting the ``refreshable`` field in the `TokenRequest`. -In recent API versions this is achieved by suffixing the requested scope with ``:refreshable``, e.g. ``orders-full:refreshable``. +Tokens may be requested to be refreshable. Merchant APIs express this by +suffixing the requested scope with ``:refreshable``, for example +``orders-full:refreshable``. The Core Bank API instead retains the +``refreshable`` field in its ``TokenRequest``. Clients must follow the +normative API of the component they use. Definition of Done ================== -* DONE: spec reviewed -* DONE: implemented in merchant backend -* implemented in libeufin-bank -* DONE: implemented in the bank webui SPA -* implemented in the merchant backoffice SPA +* [x] spec reviewed +* [x] implemented in merchant backend +* [x] implemented in libeufin-bank +* [x] implemented in the bank webui SPA +* [x] implemented in the merchant backoffice SPA Alternatives diff --git a/design-documents/050-libeufin-nexus.rst b/design-documents/050-libeufin-nexus.rst @@ -1,6 +1,23 @@ DD 50: Libeufin-Nexus ##################### +:Design status: Superseded +:Implementation status: Implemented +:DD shepherd: TBD +:Historical contributors: Christian Grothoff, Marcello Stanisci, Antoine A +:First published: 2023-09-15 +:Last substantive change: 2024-06-11 +:Implementation evidence: libeufin (2023-10-18) +:Superseded by: Current LibEuFin Nexus implementation and DD 58 transaction identifiers +:Normative references: ``libeufin/nexus-manual.rst``, ``manpages/libeufin-nexus.1.rst`` + +.. warning:: + + This document records the design that initiated the Nexus rewrite. It is + non-normative: current Nexus uses one command with subcommands, current + configuration names differ, and the transaction identifier schema evolved + as described by DD 58. Consult the LibEuFin manuals instead. + Summary ======= @@ -269,13 +286,13 @@ nexus-httpd Definition of Done ================== - * Code implemented - * Testcases migrated (including exchange, merchant, etc.) - * Man pages updated - * Manual updated - * Tested with actual banks (especially error handling and idempotency) - * Tested against server-side EBICS mock (to be resurrected) - * Tested against various ISO 20022 messages + * [x] Code implemented + * [ ] Migration of all historical exchange and merchant test cases verified + * [x] Man pages updated + * [x] Manual updated + * [ ] Testing with actual banks, including error handling and idempotency, documented + * [ ] Testing against a maintained server-side EBICS mock verified + * [ ] Coverage across the intended ISO 20022 message variants documented Alternatives diff --git a/design-documents/051-fractional-digits.rst b/design-documents/051-fractional-digits.rst @@ -1,6 +1,15 @@ DD 51: Fractional Digits ######################### +:Design status: Accepted +:Implementation status: Implemented +:DD shepherd: TBD +:Historical contributors: Sebastian, Marc Stibane, Iván Ávalos, Christian Grothoff +:First published: 2023-10-02 +:Last substantive change: 2025-07-03 +:Implementation evidence: exchange (2023-10-07), taler-ios (2023-10-24), taler-android (2024-02-12) +:Normative references: ``manpages/frags/currency-spec.rst``, ``core/exchange/get-config.rst``, ``wallet/wallet-core.md`` + Summary ======= @@ -201,11 +210,12 @@ Definition of Done DoD is not satisfied yet, a user-facing feature **must** be behind a feature flag or dev-mode flag.) - * Configuration (INI) format finalized and documented in taler.conf man page [DONE] - * Endpoints of libeufin-bank, fakebank, exchange and merchant return the information - * SPAs use the information to render amounts - * Wallet-core passes rendering information to wallet UIs - * Cashier, Android PoS, WebExtension, Android and iOS Wallet render amounts accordingly + * [x] Configuration (INI) format finalized and documented in the + ``taler.conf`` man page + * [x] Endpoints of libeufin-bank, fakebank, exchange and merchant return the information + * [x] SPAs use the information to render amounts + * [x] Wallet-core passes rendering information to wallet UIs + * [x] Cashier, Android PoS, WebExtension, Android and iOS Wallet render amounts accordingly Alternatives diff --git a/design-documents/052-libeufin-bank-2fa.rst b/design-documents/052-libeufin-bank-2fa.rst @@ -1,6 +1,22 @@ DD 52: LibEufin Bank Two-factor authentification ################################################ +:Design status: Superseded +:Implementation status: Implemented +:DD shepherd: TBD +:Historical contributors: Antoine A +:First published: 2023-12-15 +:Last substantive change: 2023-12-15 +:Implementation evidence: taler-docs (2025-09-18), libeufin (2025-10-08) +:Superseded by: Core Bank API v10 two-factor challenge protocol +:Normative references: ``core/api-corebank.rst`` + +.. warning:: + + This unresolved alternatives document is historical and non-normative. The + implemented two-factor challenge protocol is specified by the current Core + Bank API. + Summary ======= @@ -133,4 +149,4 @@ Q / A * Q: Do we need coarse-grained authorization or fine-grained is enough? - * Coarse-grained authorization requires that we store pending states for operations even for the ones that are currently oneshot. We could use a different strategy for each kind. -\ No newline at end of file + * Coarse-grained authorization requires that we store pending states for operations even for the ones that are currently oneshot. We could use a different strategy for each kind. diff --git a/design-documents/053-wallet-ui.rst b/design-documents/053-wallet-ui.rst @@ -1,6 +1,20 @@ DD 53: Wallet UI Design ####################### +:Design status: Accepted +:Implementation status: Partial +:DD shepherd: TBD +:Historical contributors: Sebastian, Iván Ávalos, Özgür Kesim, Marc Stibane, Florian Dold, Vlada Svirsh, Christian Grothoff +:First published: 2023-12-26 +:Last substantive change: 2026-03-01 +:Implementation evidence: taler-android (2024-04-17), taler-ios (2024-04-12), taler-typescript-core (2024-04-12) + +.. note:: + + This is a cross-platform living design. Individual screen tables and + ``FIXME`` entries record remaining platform work and are not claims of + completed implementation. + Summary ======= diff --git a/design-documents/054-dynamic-form.rst b/design-documents/054-dynamic-form.rst @@ -3,6 +3,20 @@ DD 54: Dynamic Forms #################### +:Design status: Accepted +:Implementation status: Implemented +:DD shepherd: TBD +:Historical contributors: Sebastian, Florian Dold, Christian Grothoff +:First published: 2024-01-02 +:Last substantive change: 2024-08-08 +:Implementation evidence: taler-typescript-core (2023-12-29) +:Normative references: :doc:`../developer/taler-developer-manual` + +.. note:: + + The shared ``web-util`` types and codecs are the source of truth where they + differ from the illustrative types in this document. + Summary ======= @@ -76,6 +90,7 @@ This is the root object of the configuration. type FormMetadata = { label: string; + description?: string; id: string; version: number; config: FormConfiguration; diff --git a/design-documents/055-wallet-problem-report.rst b/design-documents/055-wallet-problem-report.rst @@ -1,14 +1,18 @@ DD 55: Wallet Problem Reports ############################# -.. note:: - - **Status**: Early work in progress / DD number reservation. +:Design status: Rejected +:Implementation status: Not started +:DD shepherd: TBD +:Historical contributors: Florian Dold, Christian Grothoff +:First published: 2024-02-21 +:Last substantive change: 2024-03-05 .. warning:: - We concluded that we don't need the problem reports feature right now, - as all cases we care about are already covered by something else. + This rejected proposal is retained for historical context and is + non-normative. We concluded that the problem reports feature was not + needed because the relevant cases were covered by other mechanisms. Summary ======= @@ -90,7 +94,7 @@ Examples of what should NOT be a report Definition of Done ================== -TBD. +* [ ] No implementation is planned because the proposal was rejected. Alternatives ============ @@ -111,4 +115,3 @@ Discussion / Q&A * example: Exchange stops offering denomination D1. Later, it stops offering D2. Are two reports generated or is the first report changed? - diff --git a/design-documents/056-weblate-integration.rst b/design-documents/056-weblate-integration.rst @@ -1,6 +1,22 @@ DD 56: Weblate integration ########################## +:Design status: Superseded +:Implementation status: Implemented +:DD shepherd: TBD +:Historical contributors: Sebastian, Christian Grothoff +:First published: 2024-07-08 +:Last substantive change: 2024-09-02 +:Implementation evidence: taler-ios (2024-08-22) +:Superseded by: The XLIFF-based Weblate workflow in the taler-ios repository +:Normative references: :doc:`../developer/taler-developer-manual` + +.. warning:: + + The proposed pogen conversion for iOS was not the path ultimately adopted. + The iOS repository uses XLIFF files for Weblate integration. The proposal + below is retained as non-normative historical context. + Summary ======= @@ -62,7 +78,9 @@ For the integration in to weblate: The project will automatically take this values. *iOS*: - No integration has been found. + At the time this document was written, no integration had been found. The + subsequent implementation uses XLIFF files exported from the string + catalogs. *SPA*: The **strings.ts** file is not recognized by Weblate, so we generate **.po** files @@ -157,8 +175,8 @@ What we need to do to reduce the work load in the translators side Definition of Done ================== -* When iOS app has a complete semi-automated integration with weblate -* Adding msgctxt works for every platforms +* [x] iOS app has a semi-automated XLIFF integration with Weblate +* [ ] ``msgctxt`` support verified for every platform Alternatives ============ diff --git a/design-documents/057-libeufin-bank-account-lockout.rst b/design-documents/057-libeufin-bank-account-lockout.rst @@ -1,17 +1,33 @@ DD 57: LibEufin Bank Account Lockout & Recovery ############################################### +:Design status: Accepted +:Implementation status: Implemented +:DD shepherd: TBD +:Historical contributors: Antoine A, Christian Grothoff +:First published: 2024-10-21 +:Last substantive change: 2024-10-21 +:Implementation evidence: libeufin (2024-11-15) +:Normative references: :doc:`../core/api-corebank`, :doc:`../libeufin/bank-manual` + +.. note:: + + The Core Bank API is normative for authentication and lockout behavior. + Deployment-level request throttling remains an operator responsibility. + Summary ======= -LibEufin Bank should have password-based authentications lockout and recovery measures. +LibEufin Bank should have secure token-acquisition lockout and recovery +measures for password-plus-2FA authentication. Motivation ========== Currently, we allow anyone to make any number of password login attempts. This exposes us to brute-force authentication attacks and DOS password hashing attacks. We also allow unlimited creation of 2FA challenges, enabling TAN submission DOS attacks and 2FA brute forcing. -The solution would be to have a per-user attempt counter that blocks password authentication after N attemps and a per-user 2FA submission limit. +The design must limit per-user 2FA attempts without allowing an attacker who +knows only a public username to lock the victim out. Requirements ============ @@ -38,7 +54,11 @@ We will not block user accounts based on password authentication attemps, as thi If an attacker have the user's password, he will also have to solve a 2FA challenge. If he fails to often, the account will be blocked and password authentication will not longer be allowed. Existing tokens will continue to work, so if a user is already logged in with another client, they will be able to reset their password and unlock their account. Otherwise, only the administrator can unlock the account by setting a new password. -We do not limit the number of challenges created, to allow a user to log in from multiple devices at the same time for example, so it's possible for an attacker who knows a user's password to create numerous token creation challenges. Consequently, using the current per challenge attemps counter is not enough, we will also have a per account token creation attemps counter that will only be reset when a password is changed or a token created. +We allow concurrent challenges so that a user can log in from multiple devices, +but cap the number of pending challenges and rate-limit message delivery per +account. A per-challenge attempts counter is not enough, so there is also a +per-account token-creation attempts counter that is reset only when a password +is changed or a token is created. 2FA endpoints ------------- diff --git a/design-documents/058-ebics-tx-unique-id.rst b/design-documents/058-ebics-tx-unique-id.rst @@ -1,10 +1,30 @@ DD 58: EBICS Transaction Unique ID ################################## +:Design status: Accepted +:Implementation status: Implemented +:DD shepherd: TBD +:Historical contributors: Antoine A, Christian Grothoff +:First published: 2025-02-20 +:Last substantive change: 2025-02-20 +:Implementation evidence: libeufin (2025-02-25) +:Normative references: :doc:`../libeufin/nexus-manual` + +.. note:: + + The LibEuFin database schema and ISO 20022 importer are the source of truth + for the implemented identifier constraints. The SQL below illustrates the + migration design and is not a complete schema migration. + Summary ======= -LibEufin Nexus needs to have a single unique ID for each registered incoming transaction. For outgoing transaction we generate a unique ID ourselves but for incoming transaction we are dependent on whatever the bank provides. EBICS and ISO20022 do not provide a perfect transaction identifier and we need to have an ID that is compatible with different ISO20022 dialects and will be compatible with future specification changes. +LibEufin Nexus needs to identify each registered incoming transaction reliably. +For outgoing transactions we generate a unique ID ourselves, but for incoming +transactions we depend on the identifiers provided by the bank. EBICS and ISO +20022 do not provide one universally available identifier, so Nexus stores the +available identifier tuple in a form compatible with different dialects and +future specification changes. Problem ======= @@ -36,7 +56,7 @@ We should embrace this imperfection and store all the identifiers that are provi acct_svcr_ref TEXT UNIQUE CHECK (char_length(acct_svcr_ref) <= 35), tx_id TEXT UNIQUE CHECK (char_length(tx_id) <= 35), uetr UUID UNIQUE, - CONSTRAINT bank_id CHECK(COALESCE(acct_svcr_ref, tx_id, uetr) IS NOT NULL + CONSTRAINT bank_id CHECK(COALESCE(acct_svcr_ref, tx_id, uetr) IS NOT NULL) ); We should then be able to store all transaction and support UETR everywhere in the future. diff --git a/design-documents/059-statistics.rst b/design-documents/059-statistics.rst @@ -1,6 +1,15 @@ DD 59: Statistics ################# +:Design status: Accepted +:Implementation status: Implemented +:DD shepherd: TBD +:Historical contributors: Christian Grothoff +:First published: 2025-03-26 +:Last substantive change: 2025-03-26 +:Implementation evidence: merchant (2025-03-21) +:Normative references: :doc:`../core/api-merchant`, :doc:`../taler-merchant-manual`, :doc:`../core/api-exchange` + Summary ======= @@ -205,10 +214,11 @@ latest version of a customization schema or to call Definition of Done ================== -- key statistics for merchant and TOPS-deployment implemented -- REST API for merchant specified and implemented -- REST API for AML officer specified and implemented -- SPAs visualize key statistics +- [x] key merchant statistics implemented +- [x] merchant REST API specified and implemented +- [ ] TOPS-deployment statistics verified end to end +- [x] REST API for AML officers specified and implemented +- [ ] SPA visualization of all key statistics verified Alternatives ============ diff --git a/design-documents/060-clause-schnorr.rst b/design-documents/060-clause-schnorr.rst @@ -1,5 +1,20 @@ -DD 60: TODO: Clause-Schnorr Signatures -###################################### +DD 60: Clause-Schnorr Signatures +################################ + +:Design status: Accepted +:Implementation status: Implemented +:DD shepherd: TBD +:Historical contributors: Özgür Kesim +:First published: 2025-04-12 +:Last substantive change: 2025-04-12 +:Implementation evidence: exchange (2025-07-07) +:Normative references: ``core/api-exchange.rst``, ``manpages/taler-exchange-secmod-cs.1.rst`` + +.. note:: + + This DD was reserved as a design placeholder and was never expanded. The + implemented protocol and security-module manual are normative; the + placeholder sections below are retained as historical context. Summary ======= @@ -13,24 +28,26 @@ for details. Motivation ========== -TODO +Clause-Schnorr denominations need an exchange-assisted preparation step before +the wallet can blind a coin. Requirements ============ -TODO +The exchange API must expose the preparation values, and the signing helper +must support Clause-Schnorr denomination keys. Proposed Solution ================= -TODO +The implemented solution is documented by the normative exchange API and the +``taler-exchange-secmod-cs`` manual referenced above. Definition of Done ================== -(Only applicable to design documents that describe a new feature. While the -DoD is not satisfied yet, a user-facing feature **must** be behind a feature -flag or dev-mode flag.) +* [x] exchange preparation API specified and implemented +* [x] Clause-Schnorr security module implemented and documented Alternatives ============ diff --git a/design-documents/061-batched-withdraw.rst b/design-documents/061-batched-withdraw.rst @@ -1,10 +1,25 @@ -DD 61: TODO: Batched Withdraw -############################# +DD 61: Batched Withdraw +####################### + +:Design status: Accepted +:Implementation status: Implemented +:DD shepherd: TBD +:Historical contributors: Özgür Kesim +:First published: 2025-04-12 +:Last substantive change: 2025-04-12 +:Implementation evidence: taler-typescript-core (2022-05-03), exchange (2025-01-09) +:Normative references: ``core/exchange/post-withdraw.rst`` + +.. note:: + + This DD was reserved as a design placeholder and was never expanded. The + current ``POST /withdraw`` specification is normative and supersedes the + former endpoint named ``batch_withdraw``. Summary ======= -We propose to substitue the previous withdraw protocol with a variant that +We replace the previous single-coin withdraw protocol with a variant that allows for batched withdrawal of multiple coins in only one (or two, in case of Clause-Schnorr) roundtrips. @@ -18,29 +33,32 @@ coin, whenever a client wants to withdraw multiple coins. Requirements ============ -TODO +One idempotent request must be able to withdraw multiple coins from the same +reserve. Proposed Solution ================= -TODO +Use the current ``POST /withdraw`` request with arrays of denominations and +coin envelopes, as specified by the normative exchange API. Definition of Done ================== -(Only applicable to design documents that describe a new feature. While the -DoD is not satisfied yet, a user-facing feature **must** be behind a feature -flag or dev-mode flag.) +* [x] batched withdrawal implemented by wallet-core +* [x] current ``POST /withdraw`` endpoint specified and implemented +* [x] former ``batch_withdraw`` endpoint removed Alternatives ============ -TODO +Retain one request per coin, with the associated extra round trips. Drawbacks ========= -TODO +The request and response are larger and clients must persist all coin inputs +before sending the request. Discussion / Q&A ================ diff --git a/design-documents/062-pq-refresh.rst b/design-documents/062-pq-refresh.rst @@ -1,6 +1,23 @@ DD 62: PQ Refresh Protocol ########################## +:Design status: Superseded +:Implementation status: Implemented +:DD shepherd: TBD +:Historical contributors: Özgür Kesim, Christian Grothoff +:First published: 2025-04-12 +:Last substantive change: 2025-11-25 +:Implementation evidence: exchange (2025-04-14) +:Superseded by: Exchange protocol v32 refresh (vDOLDPLUS) +:Normative references: ``core/exchange/post-melt.rst``, ``core/exchange/post-reveal-melt.rst`` + +.. warning:: + + This signature-derived refresh design was implemented and then superseded. + It is non-normative and conflicts with protocol v32, which uses ECDHE + transfer public keys and revealed batch seeds. Implementations must follow + the current exchange API. + Summary ======= This document specifies a change to GNU Taler's refresh protocol that provides diff --git a/design-documents/063-libeufin-conversion-rate-classes.rst b/design-documents/063-libeufin-conversion-rate-classes.rst @@ -1,6 +1,21 @@ DD 63: LibEufin Conversion Rate Class ##################################### +:Design status: Accepted +:Implementation status: Implemented +:DD shepherd: TBD +:Historical contributors: Antoine A, Sebastian, Florian Dold +:First published: 2025-05-12 +:Last substantive change: 2025-07-01 +:Implementation evidence: libeufin (2025-07-16) +:Normative references: ``core/api-corebank.rst``, ``core/api-bank-conversion-info.rst`` + +.. note:: + + API version numbers and endpoint descriptions below record the migration + plan. The current Core Bank and Conversion API specifications are + normative. + Summary ======= @@ -145,14 +160,17 @@ Taler Conversion Info API The version changes to v2. -We need to move the current conversion-info API from ``/conversion-info/*`` to ``/accounts/$USERNAME/conversion-info/*`` to take into account user specific conversion rate. +The migration moved the conversion-info API from ``/conversion-info/*`` to +``/accounts/$USERNAME/conversion-info/*`` to take user-specific conversion +rates into account. A ``/rate`` to get, the potentially private, user specific conversion rate. Taler Core Bank API ------------------- -The version changes to v9. +The design targeted Core Bank API v9. The current normative Core Bank API has +since advanced beyond that version. Deprecated API that should not longer be used: @@ -192,8 +210,9 @@ Added sub-api ``/accounts/$USERNAME/conversion-info/*``. This is used by normal There are also new error code reported by the API, like ``TALER_EC_BANK_CONVERSION_RATE_CLASS_UNKNOWN`` when the client is trying to create or update an account. -TODO: Add to the spec -^^^^^^^^^^^^^^^^^^^^^ - -* Add missing error code so the client can create better error message for those +Specification follow-up +^^^^^^^^^^^^^^^^^^^^^^^ +The conversion-rate-class endpoints and error codes are now part of the +normative Core Bank API. Clients should use that specification rather than +the historical endpoint inventory above. diff --git a/design-documents/064-kyc-operation-algo.rst b/design-documents/064-kyc-operation-algo.rst @@ -1,6 +1,15 @@ DD 64: Algorithm for transactions with KYC checks ################################################# +:Design status: Accepted +:Implementation status: Implemented +:DD shepherd: TBD +:Historical contributors: Florian Dold, Christian Grothoff +:First published: 2025-06-05 +:Last substantive change: 2025-07-30 +:Implementation evidence: taler-typescript-core (2025-07-08) +:Normative references: :doc:`../developer/taler-wallet-developer`, :doc:`../wallet/wallet-core`, :doc:`../core/api-exchange` + Summary ======= @@ -72,7 +81,7 @@ Processing 3. Handle the ``/kyc-check/...`` response: - * Set ``same_resp := resp.status == last_check_status and resp.code == last_check_status and resp.rule_gen == last_rule_gen``. + * Set ``same_resp := resp.status == last_check_status and resp.code == last_check_code and resp.rule_gen == last_rule_gen``. * Set ``last_check_status := resp.status``, ``last_check_code := resp.code``, ``last_rule_gen := resp.rule_gen`` * If ``same_resp == true``: finish processing operation with result ``BACKOFF``. * If ``resp.status == 204 No Content``: Set ``last_deny := null``. Finish processing operation with result ``PROGRESS`` (effectively @@ -128,7 +137,8 @@ Additional Considerations Definition of Done ================== -N/A +* [x] shared transaction/KYC retry algorithm implemented in wallet-core +* [x] deposit, peer-to-peer and withdrawal paths use the shared algorithm Alternatives ============ diff --git a/design-documents/065-exchange-base-url-migration.rst b/design-documents/065-exchange-base-url-migration.rst @@ -1,6 +1,20 @@ DD 65: Exchange Base URL Migration ################################## +:Design status: Accepted +:Implementation status: Implemented +:DD shepherd: TBD +:Historical contributors: Florian Dold +:First published: 2025-06-25 +:Last substantive change: 2025-06-25 +:Implementation evidence: taler-typescript-core (2025-06-23) +:Normative references: :doc:`../developer/taler-wallet-developer`, :doc:`../wallet/wallet-core` + +.. note:: + + Wallet migration support is implemented. The operator sequence in this DD + has not yet been promoted to a deployment reference manual. + Summary ======= @@ -40,9 +54,8 @@ The wallet runs a migration check when one of the following conditions applies: * C1 (unavaliable exchange): - * The wallet updates an exchange entry (manually or scheduled), requests ``/keys``, and encounters - either an error response. - exchange entry. + * The wallet updates an exchange entry (manually or scheduled), requests + ``/keys``, and encounters an error response. * There is a migration plan for the old exchange to a new exchange. * The new exchange returns a well-formed ``/keys`` response with a ``base_url`` that matches the new exchange base URL @@ -90,7 +103,9 @@ completed. Definition of Done ================== -N/A +* [x] wallet-core applies configured base-URL migration plans +* [x] migration behavior has wallet-core test coverage +* [ ] operator migration procedure promoted to a deployment reference manual Alternatives ============ diff --git a/design-documents/066-wallet-color-scheme.rst b/design-documents/066-wallet-color-scheme.rst @@ -1,6 +1,21 @@ DD 66: Wallet UI Color Scheme ============================= +:Design status: Accepted +:Implementation status: Partial +:DD shepherd: TBD +:Historical contributors: Vlada Svirsh +:First published: 2025-07-16 +:Last substantive change: 2026-07-05 +:Implementation evidence: taler-android (2025-07-10), taler-ios (2026-06-05) +:Normative references: :doc:`../developer/taler-wallet-developer` + +.. note:: + + Native-wallet adoption is in progress. WebExtension dark-mode support, + complete semantic-token adoption, contrast verification and developer + onboarding remain incomplete. + Summary ------- @@ -541,12 +556,12 @@ Outline Definition of Done ------------------ -- Theming system supports all defined roles -- All components use semantic color tokens -- Tokens switch correctly in light/dark mode -- WCAG 2.1 AA contrast verified -- Color role documentation added to developer onboarding -- Feature flag enables color system switch before full rollout +- [x] Android theming system supports the defined Material 3 roles +- [x] native-wallet themes switch between light and dark mode +- [ ] WebExtension supports dark mode and the complete role set +- [ ] all components use semantic color tokens +- [ ] WCAG 2.1 AA contrast verified across all wallet screens +- [ ] color role documentation added to developer onboarding Alternatives ------------ @@ -563,6 +578,3 @@ Drawbacks Discussion / Q&A ---------------- - - - diff --git a/design-documents/067-merchant-self-provisioning.rst b/design-documents/067-merchant-self-provisioning.rst @@ -1,7 +1,20 @@ DD 67: Merchant Self Provisioning ################################# -*Status*: incomplete draft (2025-07-31) +:Design status: Accepted +:Implementation status: Implemented +:DD shepherd: TBD +:Historical contributors: Florian Dold, Sebastian, Christian Grothoff +:First published: 2025-07-31 +:Last substantive change: 2025-08-03 +:Implementation evidence: taler-typescript-core (2025-08-05), merchant (2025-08-06), sandcastle-ng (2025-10-30) +:Normative references: ``core/api-merchant.rst``, ``taler-merchant-manual.rst``, ``manpages/taler-merchant.conf.5.rst`` + +.. note:: + + Self-provisioning is implemented. The API, operator manual and + configuration man page are normative where they differ from this planning + document. Summary ======= @@ -24,7 +37,8 @@ Requirements Timeline ======== -Ideally, available by Sept. 1st 2025. +The original target was September 1, 2025. The feature subsequently landed; +this date is retained as historical planning context. Proposed Solution ================= @@ -34,7 +48,8 @@ Implementation tasks: * Merchant backend * A sysadmin tool to skip the requirement of 2fa channel for instances that are not self provisioned (like blog) - * New configuration option ALLOW_SIGNUP: boolean in ``[merchant]`` section with default to ``false`` + * New configuration option ``ENABLE_SELF_PROVISIONING`` in the + ``[MERCHANT]`` section, defaulting to ``NO`` * New public endpoint for self-provisioned instance creation * New (private) endpoints for 2FA channel confirmation * New public endpoints for password reset @@ -128,8 +143,8 @@ Signup page: Definition of Done ================== -* Children of tracking bug (https://bugs.taler.net/n/10224) all closed -* Integration tests passing +* [ ] closure of every child of tracking bug https://bugs.taler.net/n/10224 verified +* [x] integration-test coverage added Drawbacks and Alternatives ========================== diff --git a/design-documents/068-tokens-roadmap.rst b/design-documents/068-tokens-roadmap.rst @@ -1,7 +1,20 @@ DD 68: Token Feature Roadmap ############################ -*Status*: incomplete draft (2025-07-31) +:Design status: Draft +:Implementation status: Partial +:DD shepherd: TBD +:Historical contributors: Vlada Svirsh, Florian Dold +:First published: 2025-07-31 +:Last substantive change: 2025-11-28 +:Implementation evidence: taler-typescript-core (2025-09-22), sandcastle-ng (2025-09-25) +:Normative references: ``core/api-donau.rst``, ``core/api-merchant.rst``, ``wallet/wallet-core.md`` + +.. note:: + + This remains a roadmap. Existing Donau, merchant and wallet APIs are + normative for implemented functionality; subscription, discount and asset + milestones below do not imply implementation. Summary ======= @@ -17,7 +30,7 @@ Plan for Wallet Types of tokens: -* donations tokens (hard deadline: End of November) +* donation tokens (original hard deadline: end of November 2025) * onboarding (1st donation) @@ -52,7 +65,7 @@ Types of tokens: * group by expiration date (if it exists) * delete -* asset tokens (deadlines: end of March) +* asset tokens (original deadline: end of March 2026) * listing (with number, no fractions possible, no expiration) * background task: poll for share action, automatically execute the share action @@ -272,9 +285,9 @@ Donau verification (verified) Definition of Done ================== -* Donau deployed in sandcastle -* donations in demo must use donau / contracttermsv1 -* use separate app (prototype exists?) for verification of receipts +* [x] Donau deployed in sandcastle +* [x] demo donation setup uses Donau and contract terms v1 +* [ ] separate receipt-verification app completed and deployment verified Discussion / Q&A ================ diff --git a/design-documents/069-exchange-base-url-completion.rst b/design-documents/069-exchange-base-url-completion.rst @@ -1,6 +1,16 @@ DD 69: Exchange Base URL Completion ################################### +:Design status: Accepted +:Implementation status: Implemented +:DD shepherd: TBD +:Historical contributors: Vlada Svirsh +:First published: 2025-09-16 +:Last substantive change: 2025-11-22 +:Implementation evidence: ``taler-typescript-core`` (2025-09-15; 2026-07-31) +:Normative references: ``wallet/wallet-core.md`` (exchange-base-URL completion operation) +:Upstream follow-up: Regenerate/fix ``wallet/wallet-core.md``: its operation comment incorrectly describes coin refresh, and the generated request/result omit ``progressToken``/``suggestions`` that are present in the implementation. Do not treat the generated text as the authoritative completion algorithm until corrected. + Summary ======= @@ -60,7 +70,8 @@ Process: * Check the input against a local list of trusted exchanges. * Match by exact part match of hostname and fuzzy match (≥70% Levenshtein). - * Return ``bad-protocol`` and if trusted entry(ies) is(are) found, return it(them) back in object(``sugestions: array``). + * Return ``bad-exchange`` and, if trusted entries are found, return them in + the ``suggestions`` array. Outcome values -------------- @@ -68,7 +79,7 @@ Outcome values * **ok** — Keys validated; return canonical base. * **bad-syntax** — Input invalid (e.g., non-HTTPS scheme). * **bad-network** — Network failure (DNS/connect/TLS/timeout). -* **bad-protocol** — Response received but not a valid exchange. +* **bad-exchange** — Response received but not a valid exchange. Canonicalization of output -------------------------- @@ -84,7 +95,7 @@ Examples If not valid, then try ``https://exchange.example.com/config``. If that works → **ok**, returns ``https://exchange.example.com/``. * ``https://exchange.example.com/`` with ``/config`` returning something other - than a valid `ExchangeVersionResponse <https://docs.taler.net/core/api-exchange.html#get--config>`__ object -> **bad-protocol**. + than a valid `ExchangeVersionResponse <https://docs.taler.net/core/api-exchange.html#get--config>`__ object -> **bad-exchange**. * ``http://exchange.example.com`` -> **bad-syntax** (HTTPS required). * ``example.com`` where ``/config`` redirects to ``https://api.example.com/config`` and returns valid data -> **ok**, returns @@ -95,13 +106,13 @@ Examples Definition of Done ================== -* Request implemented and documented. +* [x] Request implemented and documented. * Unit tests cover: - valid inputs, - redirects, - trusted exchange fallback, - failure cases (syntax, network, protocol). -* Feature is enabled by default once tests pass. +* [x] Feature is enabled by default. Alternatives ============ diff --git a/design-documents/070-alias-directory-mailbox.rst b/design-documents/070-alias-directory-mailbox.rst @@ -1,6 +1,15 @@ DD 70: Alias Lookup and Mailbox ############################### +:Design status: Accepted +:Implementation status: Partial +:DD shepherd: TBD +:Historical contributors: Martin Schanzenbach +:First published: 2025-09-19 +:Last substantive change: 2025-11-10 +:Implementation evidence: ``taler-typescript-core`` (2025-11-07; 2026-07-14; 2026-07-16; 2026-08-20) +:Normative references: ``core/api-mailbox.rst`` and ``core/mailbox/get-H_MAILBOX.rst`` + Summary ======= @@ -248,6 +257,13 @@ For example, DNS or GNS validators will publish the mappings under zones of the Mailbox ------- +.. note:: + + The normative mailbox API now specifies exactly 256-byte messages beginning + with the sender's ephemeral public key; see + :ref:`api-mailbox`. The type-prefixed framing below records an earlier + proposal and is not the current wire format. + Messages are retuned from the API with a fixed length. The configured messages length must be obtained through the mailbox service configuration endpoint. @@ -255,7 +271,8 @@ The first two bytes of the message are 16 bit unsigned integers in network byte order that specify the message type. The remaining bytes contain the encrypted message (including the MAC). Messages are encrypted using HPKE (X25519 with ChaChaPoly1305 as AEAD). -Currently, there is only a single message type that carries a taler URI as payload. +The proposed outer framing has a single message type carrying a Taler URI; +after decryption, the payload is one of the two URI variants defined below. This type is identified by the bytes ``0x00 0x00``. This message type number is in network byte order prefixed before the HPKE ciphertext. The HPKE ciphertext starts with a 32 byte diff --git a/design-documents/071-auto-refresh.rst b/design-documents/071-auto-refresh.rst @@ -1,6 +1,14 @@ DD 71: Auto-refresh ################### +:Design status: Accepted +:Implementation status: Prototype +:DD shepherd: TBD +:Historical contributors: Christian Grothoff +:First published: 2025-10-23 +:Last substantive change: 2025-10-23 +:Implementation evidence: ``taler-typescript-core`` (2026-08-19, not merged into the reviewed HEAD) + Summary ======= @@ -104,10 +112,11 @@ Proposed Solution Definition of Done ================== -* Implemented in wallet-core -* Changes to interactions for signalling warnings to GUIs -* dev-experiments exist to trigger special alerts to users -* GUIs have been designed and tested +* [x] Prototype implemented in a wallet-core feature branch +* [ ] Prototype merged into the main branch +* [ ] Changes to interactions for signalling warnings to GUIs +* [ ] Dev experiments exist to trigger special alerts to users +* [ ] GUIs have been designed and tested Alternatives diff --git a/design-documents/072-products-units.rst b/design-documents/072-products-units.rst @@ -1,6 +1,15 @@ DD 72: Products Units ##################### +:Design status: Accepted +:Implementation status: Partial +:DD shepherd: TBD +:Historical contributors: Bohdan Potuzhnyi, Vlada Svirsh +:First published: 2025-10-29 +:Last substantive change: 2025-11-02 +:Implementation evidence: ``merchant`` (2025-10-18); backend and API support landed, client coverage remains incomplete +:Normative references: ``core/merchant/post-private-products.rst``, ``core/merchant/patch-private-units-UNIT.rst``, and ``core/merchant/get-templates-TEMPLATE_ID.rst`` + Summary ======= @@ -43,7 +52,7 @@ Requirements marking them deprecated once ``unit_*`` alternatives exist. When both are supplied the backend must check that values match. * **Use a predictable format:** fixed-point decimal strings - ``INTEGER[.FRACTION]`` with up to eight fractional digits; reject scientific + ``INTEGER[.FRACTION]`` with up to six fractional digits; reject scientific notation and special floating-point tokens. * **Provide backend-chosen defaults per unit identifier** so new front-ends can present appropriate UI without manual configuration. @@ -179,9 +188,9 @@ Proposed Solution unit_active?: boolean; } - Built-in units accept changes only to ``unit_allow_fraction`` and - ``unit_precision_level``. Custom units may update every attribute except - ``unit``. + Built-in units accept changes only to ``unit_allow_fraction``, + ``unit_precision_level``, and ``unit_active``. Custom units may update + every attribute except ``unit``. .. http:delete:: /private/units/$UNIT @@ -426,15 +435,15 @@ Proposed Solution 7. **Quantity presentation in wallets and orders** When displaying order details or cart lines, wallet and POS front-ends - **MUST use the short unit label** returned by ``GET /private/units`` (or - ``GET /private/units/$UNIT``) for the referenced ``unit``. When the unit - catalogue does not contain the identifier, clients fall back to the raw - ``unit`` string. Append the selected label to the numeric value with a + **MUST use the short unit label embedded in the public template response** + for the referenced ``unit``. Wallets cannot call the authenticated + ``/private/units`` endpoints. When no label is supplied, clients fall back + to the raw ``unit`` string. Append the selected label to the numeric value with a non-breaking thin space (U+202F). Trailing zeros *up to* the declared ``unit_precision_level`` **MUST be trimmed**, but the displayed precision **MUST NOT** exceed the declared level. Examples:: - 1.500 kg → shown as 1.500 kg + 1.500 kg → shown as 1.5 kg 3.00 pc → shown as 3 pc For precision 0 units the fractional part is omitted entirely. @@ -506,17 +515,17 @@ Definition of Done DoD is not satisfied yet, a user-facing feature **must** be behind a feature flag or dev-mode flag.) -* Merchant backend accepts and emits the new metadata for product CRUD, +* [x] Merchant backend accepts and emits the new metadata for product CRUD, inventory locks, and order creation. -* Merchant SPA surfaces a unit drop-down populated from ``GET /private/units``, +* [ ] Merchant SPA surfaces a unit drop-down populated from ``GET /private/units``, uses ``unit_total_stock`` in product listings, allows fractional orders where permitted, and provides a management screen for the unit catalogue. -* POS and wallet reference implementations render fractional quantities +* [ ] POS and wallet reference implementations render fractional quantities according to ``unit_allow_fraction`` / ``unit_precision_level``, allows to create orders with fractional quantities of products. -* Legacy clients continue to function using the integer fields, with +* [ ] Legacy clients continue to function using the integer fields, with automated tests ensuring that canonical and legacy values stay in sync. -* Wallets implement the presentation and localisation guidance described in +* [ ] Wallets implement the presentation and localisation guidance described in steps 7 and 8 of this section. Alternatives diff --git a/design-documents/073-extended-merchant-template.rst b/design-documents/073-extended-merchant-template.rst @@ -1,6 +1,15 @@ DD 73: Extended Merchant Template ################################# +:Design status: Accepted +:Implementation status: Partial +:DD shepherd: TBD +:Historical contributors: Bohdan Potuzhnyi +:First published: 2025-11-04 +:Last substantive change: 2025-11-11 +:Implementation evidence: ``merchant`` (2025-11-15); backend and wallet protocol support landed, while merchant WebUI creation remains incomplete +:Normative references: ``core/api-merchant.rst`` and ``core/merchant/get-templates-TEMPLATE_ID.rst`` + Summary ======= @@ -65,7 +74,9 @@ Requirements product descriptors, selection rules, and customer-editable defaults. * Extend the template instantiation ``POST`` to carry the selected products and quantities, reusing the ``TemplateDetails`` object. -* Remain compatible with templates from protocol versions v13+. +* Preserve handling of legacy template types from protocol versions v13+; + clients that do not support the new inventory-cart type must reject that + type cleanly. Proposed Solution ================= @@ -168,8 +179,9 @@ New contract type has next structure: } Wallets that do not recognise ``"inventory-cart"`` continue to expect -template-level fields such as ``minimum_age``, and when new type supplied -it will inevitably, KABOOM! +template-level fields such as ``minimum_age``. They must reject the unknown +template type cleanly instead of attempting to interpret it as a legacy +template. The merchant simply saves id's of ``selected_categories`` and ``selected_products``. @@ -273,12 +285,14 @@ per-product logic when available. // Contains all categories referenced by the products. categories: WalletInventoryCategory[]; + + // Contains all custom units referenced by the products. + units: WalletInventoryUnit[]; } -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 -share a single meaning for every field, yet we lower the number of requests between the -wallet and backend. +The following structures mirror the protocol-v25 inventory payload so that the +backend, SPA, and wallet share a single meaning for every field while keeping +the inventory available in one response. .. ts:def:: WalletInventoryProduct @@ -286,15 +300,14 @@ wallet and backend. product_id: Slug; product_name: string; description: string; - description_i18n: { [lang_tag: string]: string }; + description_i18n?: { [lang_tag: string]: string }; taxes?: Tax[]; unit: Slug; - // Optional translations for non-standard units. - unit_name_short_i18n?: { [lang_tag: string]: string }; unit_prices: Amount[]; unit_allow_fraction: boolean; unit_precision_level: Integer; - categories?: Integer[]; + remaining_stock: DecimalQuantity; + categories: Integer[]; image_hash?: string; } @@ -306,6 +319,18 @@ wallet and backend. category_name_i18n?: { [lang_tag: string]: string }; } +.. ts:def:: WalletInventoryUnit + + interface WalletInventoryUnit { + unit: Slug; + unit_name_long: string; + unit_name_long_i18n?: { [lang_tag: string]: string }; + unit_name_short: string; + unit_name_short_i18n?: { [lang_tag: string]: string }; + unit_allow_fraction: boolean; + unit_precision_level: Integer; + } + This design lets wallets download hundreds of objects in a single request and fetch images later via the shared ``GET /instances/$ID/products/$IMAGE_HASH/image`` endpoint. @@ -358,21 +383,21 @@ Wallets handle inventory templates as follows: Compatibility rules ------------------- -* Docs mark templates containing ``template_type`` = - ``"inventory-cart"`` as requiring protocol vNEXT (final version TBD) or later. +* Templates containing ``template_type`` = ``"inventory-cart"`` require + merchant protocol v25 or later. * QR codes stay in the same pay-template URI parameters. Definition of Done ================== -* REST API changes and schema extensions are ratified by wallet, merchant, and - SPA. -* Integration tests cover single-product and multi-product cart creation via - the new template type. -* Updated reference documentation (merchant manual) describes the new - template type and associated fields. -* Wallet and merchant SPA have defined workflows and designs - for the new template. +* [x] REST API changes and schema extensions are ratified by wallet and merchant. +* [ ] Merchant SPA support for creating inventory-cart templates. +* [ ] Integration tests cover single-product and multi-product cart creation via + the new template type across merchant and wallet. +* [x] Updated reference documentation describes the new template type and + associated fields. +* [ ] Wallet and merchant SPA have complete workflows and designs for the new + template. Alternatives diff --git a/design-documents/074-merchant-backend-simplification.rst b/design-documents/074-merchant-backend-simplification.rst @@ -1,7 +1,12 @@ DD 74: Merchant Backend Simplification ###################################### -Status: incomplete draft +:Design status: Draft +:Implementation status: Not started +:DD shepherd: TBD +:Historical contributors: Florian Dold, Christian Grothoff, Sebastian +:First published: 2025-11-13 +:Last substantive change: 2026-02-05 Summary ======= @@ -372,8 +377,6 @@ Suggested restructuring: * For PoS access tokens * For turnstile, wordpress, etc. - * ``OTP Devices`` (only for payment confirmation, *not* for login security!) - * ``About`` * Version of UI @@ -386,15 +389,15 @@ Sidebar Simplification * Remove Wire transfers section (now redundant) * Remove KYC Status section (now redundant) -* Remove OTP (now under settings) +* Remove OTP (now under Templates) * Remove Webhooks (now under settings) * Remove Passwords (now under settings) * Remove Access Tokens (now under settings) * Remove Personalization (now under settings) * Remove merchant backoffice domain (now under settings->about) * Move user login name at the top (instead of version) -* Remove version number (now under settings->amount) -* Remove lavels "Configuration" / "Connection" +* Remove version number (now under settings->about) +* Remove labels "Configuration" / "Connection" Definition of Done ================== @@ -425,4 +428,3 @@ Discussion / Q&A * Is the chosen persona persistent? * Not for now, it's stored per local-storage. - diff --git a/design-documents/075-wallet-bban-support.rst b/design-documents/075-wallet-bban-support.rst @@ -1,6 +1,15 @@ DD 75: Wallet support for BBAN entry/display ############################################ +:Design status: Accepted +:Implementation status: Partial +:DD shepherd: TBD +:Historical contributors: Florian Dold +:First published: 2025-11-18 +:Last substantive change: 2025-12-16 +:Implementation evidence: ``taler-typescript-core`` (2025-12-04; 2026-07-18); ``taler-ios`` (2026-02-15) +:Normative references: :doc:`../developer/taler-wallet-developer`, :doc:`../wallet/wallet-core` + Summary ======= @@ -54,7 +63,7 @@ Wallet-core: * The ``getDepositWireTypes`` request returns a ``preferredEntryType: "iban" | "bban"`` flag for every payto URI of target tpye ``"iban"``. -In order to allow copy+pasting an IBAN into a BBAN field, the ``convertBbanToPaytoIban`` must +In order to allow copy+pasting an IBAN into a BBAN field, ``convertIbanAccountFieldToPayto`` must also accept actual IBANs as input and convert them to a payto URI. @@ -74,9 +83,10 @@ Wallet UIs should either: Definition of Done ================== -* Implemented in wallet-core -* Implemented in the Android, webext and iOS wallets -* Tested in a QC session with a HUF-style deployment +* [x] Implemented in wallet-core +* [ ] Implemented in the Android, WebExtension and iOS wallets (iOS preparation + has landed; complete cross-platform coverage was not established) +* [ ] Tested in a QC session with a HUF-style deployment Alternatives ============ diff --git a/design-documents/076-paywall-proxy.rst b/design-documents/076-paywall-proxy.rst @@ -1,6 +1,15 @@ DD 76: Paivana - Fighting AI Bots with GNU Taler ################################################ +:Design status: Accepted +:Implementation status: Implemented +:DD shepherd: TBD +:Historical contributors: Florian Dold, Christian Grothoff +:First published: 2025-11-26 +:Last substantive change: 2026-08-07 +:Implementation evidence: ``merchant`` (2026-01-20; 2026-04-25; 2026-04-27; 2026-08-04); ``paivana`` (2026-04-19) +:Normative references: ``taler-paivana-manual.rst``, ``frags/paivana-httpd-manual.rst``, and ``core/api-merchant.rst`` + Summary ======= @@ -148,7 +157,7 @@ Steps: * The JavaScript of the paywall page (or the non-JS client processing the ``Paivana`` HTTP header) then POSTs the order ID, ``nonce``, ``expiration`` - and ``website`` to ``{domain}/.well-known/pavivana``. + and ``website`` to ``{domain}/.well-known/paivana``. In this JSON request, the ``nonce`` is ``crock32``-encoded and ``expiration`` is a normal GNU Taler timestamp object (``{"t_s": ...}``, in seconds); the server re-derives the binary @@ -364,17 +373,14 @@ done since well before this design; where a genuine HTTP/1.0 client is expected, the upstream should be configured to declare a ``Content-Length``, which restores detection for it too. -Implementation: ---------------- +Implementation +-------------- -* Merchant backend needs way to lookup order IDs under a ``session_id`` - (DONE: e027e729..b476f8ae) -* Merchant backend needs way to instantiate templates with - a given ``session_id`` and ``fulfillment_url``. This also - requires extending the allowed responses for templates in general. -* Paivana component needs to be implemented -* Wallet-core needs support for a ``session_id`` and - ``fulfillment_url`` in pay templates. +* [x] Merchant backend can look up order IDs under a Paivana session ID. +* [x] Merchant backend can instantiate Paivana templates with ``paivana_id`` + and the target website. +* [x] Paivana component implemented. +* [x] Wallet/Web utility support implemented. Test Plan @@ -385,7 +391,9 @@ Test Plan Definition of Done ================== -N/A +* [x] Merchant, Paivana, and wallet-side protocol support implemented. +* [x] Protocol and operator documentation published. +* [ ] Production deployment and end-to-end QC recorded. Alternatives ============ diff --git a/design-documents/077-merchant-self-provisioning.rst b/design-documents/077-merchant-self-provisioning.rst @@ -1,6 +1,19 @@ DD 77: Merchant Multi-Tenancy and Self-Provisioning ################################################### +:Design status: Abandoned +:Implementation status: Not started +:DD shepherd: TBD +:Historical contributors: Martin Schanzenbach +:First published: 2025-12-11 +:Last substantive change: 2025-12-11 + +.. warning:: + + This proposal was abandoned. The OIDC-based multi-tenancy model below was + not implemented and must not be treated as the merchant authentication or + provisioning contract. + Summary ======= diff --git a/design-documents/078-taxes.rst b/design-documents/078-taxes.rst @@ -1,13 +1,23 @@ DD 78: Taxes ############ +:Design status: Accepted +:Implementation status: Partial +:DD shepherd: TBD +:Historical contributors: Christian Grothoff +:First published: 2025-12-22 +:Last substantive change: 2025-12-26 +:Implementation evidence: ``merchant`` (2025-12-27; 2025-12-28; 2025-12-29) implements the product-group and money-pot foundation; tax rules remain future work +:Normative references: ``core/api-merchant.rst`` (product groups, money pots, and upcoming ``vTAXES``) + Summary ======= We've received various requests for the merchant backend to provide transaction reports for accountants. While not always stated explicitly, we believe this is largely also related to tax reporting. This document explains -the plan for how we intend to deal with periodic reporting. +the plan for tax calculation and tax data; periodic report delivery is covered +by DD 79. Motivation ========== @@ -292,9 +302,12 @@ Test Plan Definition of Done ================== -* Specification updated -* Database updated -* Merchant backend updated: +The product-group and money-pot foundation has landed. The tax protocol is +still listed as upcoming, so the tax-specific items below remain incomplete. + +* [ ] Specification promoted from upcoming to current +* [ ] Database updated with tax definitions +* [ ] Merchant backend updated: * CRUD API for tax definitions * INI-based tax class importer @@ -302,7 +315,7 @@ Definition of Done * Order creation update * Statistics update on order paid -* Merchant backend SPA updated: +* [ ] Merchant backend SPA updated: * CRUD for tax class definitions * CRUD for associating tax classes with products @@ -310,7 +323,7 @@ Definition of Done not necessarily per-product) * Statistics page rendering tax statistics -* Wallets updated to render taxes (upon request, in detailed view +* [ ] Wallets updated to render taxes (upon request, in detailed view on payment or from order history) diff --git a/design-documents/079-reports.rst b/design-documents/079-reports.rst @@ -1,6 +1,15 @@ DD 79: Reports ############## +:Design status: Accepted +:Implementation status: Implemented +:DD shepherd: TBD +:Historical contributors: Christian Grothoff +:First published: 2025-12-22 +:Last substantive change: 2025-12-26 +:Implementation evidence: ``merchant`` (2025-12-26; 2025-12-28; 2026-01-07) +:Normative references: ``core/merchant/post-private-reports.rst``, ``core/merchant/get-config.rst``, and ``manpages/taler-merchant.conf.5.rst`` + Summary ======= @@ -78,20 +87,18 @@ Test Plan Definition of Done ================== -* Specification updated -* Database updated -* Merchant backend updated: +* [x] Specification updated +* [x] Database updated +* [x] Merchant backend updated: * CRUD API for report definitions * INI-based configuration for reporting helper programs * New background process for creating reports * New endpoints for generating reports (#9361) -* Merchant backend SPA updated: - - * CRUD for report definitions - * Statistics (?) page with links to various - GET pages that generate (PDF, CSV) reports (#10487) +* [x] Merchant backend SPA updated with CRUD for report definitions +* [ ] Statistics page with links to GET pages that generate PDF/CSV reports + (#10487) verified and manually tested Alternatives diff --git a/design-documents/080-short-wire-subject.rst b/design-documents/080-short-wire-subject.rst @@ -1,6 +1,15 @@ DD 80: Alternative wire transfer subjects ######################################### +:Design status: Accepted +:Implementation status: Partial +:DD shepherd: TBD +:Historical contributors: Antoine A, Christian Grothoff +:First published: 2026-01-13 +:Last substantive change: 2026-03-04 +:Implementation evidence: ``exchange`` (2026-02-28); the landed registration protocol differs from parts of this proposal +:Normative references: ``core/api-bank-transfer.rst`` and ``core/bank-transfer/post-registration.rst`` + Summary ======= @@ -58,6 +67,14 @@ be used each time. Proposed Solution ================= +.. note:: + + The landed prepared-transfer protocol consolidates account allocation and + authorization-key registration in ``POST /registration``. It does not use + the separate subject-generation/mapping endpoints or adaptive proof-of-work + described in the historical proposal below. The normative prepared- + transfer API takes precedence. + Wire transfer subject generation -------------------------------- @@ -173,14 +190,18 @@ Test Plan Definition of Done ================== -* New API supported by all wire gateways -* Support for Swiss QR Bill wire transfer subjects -* Exchange points wallets/merchants to wire transfer API -* Wallets support registration -* Wallets have UI where the user can specify "periodic" +Only the prepared-transfer API and exchange registration client have been +established from current-tree evidence; the remaining deployment and UI items +are intentionally unchecked. + +* [ ] New API supported by all wire gateways +* [x] Prepared-transfer API specifies Swiss QR Bill wire transfer subjects +* [x] Exchange registration client supports the wire transfer API +* [ ] Wallets support registration +* [ ] Wallets have UI where the user can specify "periodic" wire transfers where the wallets periodically try to map new reserve public keys to an existing registration -* *Optional*: remove legacy mode? +* [ ] *Optional*: remove legacy mode? Alternatives diff --git a/design-documents/081-shop-discovery.rst b/design-documents/081-shop-discovery.rst @@ -1,6 +1,15 @@ DD 81: Shop Discovery ##################### +:Design status: Accepted +:Implementation status: Partial +:DD shepherd: TBD +:Historical contributors: Florian Dold +:First published: 2026-01-20 +:Last substantive change: 2026-01-20 +:Implementation evidence: ``exchange`` (2024-09-12); ``taler-typescript-core`` (2025-11-27); ``taler-android`` (2026-01-27); ``taler-ios`` (2026-03-10) +:Normative references: ``core/exchange/get-keys.rst`` and ``wallet/wallet-core.md`` + Summary ======= @@ -98,7 +107,7 @@ Description: user currently has selected. * When there are no shopping URLs available, the UI element - is now shown. + is not shown. * TBD: What happens when no currency scope is selected, i.e. the user is on the overview screen? @@ -138,9 +147,9 @@ Definition of Done * [x] Implemented in exchange * [x] Implemented in wallet-core -* [ ] Consensus on DD -* [ ] Implemented on Android UI -* [ ] Implemented on iOS UI +* [x] Consensus on DD +* [x] Implemented on Android UI +* [x] Implemented on iOS UI * [ ] Implemented on webext UI * [ ] QC session with Android UI * [ ] QC session with iOS UI diff --git a/design-documents/082-wallet-diagnostics.rst b/design-documents/082-wallet-diagnostics.rst @@ -1,6 +1,16 @@ DD 82: Wallet Diagnostics Export ################################ +:Design status: Accepted +:Implementation status: Partial +:DD shepherd: TBD +:Historical contributors: Florian Dold +:First published: 2026-02-12 +:Last substantive change: 2026-02-12 +:Implementation evidence: ``taler-typescript-core`` (2026-02-13); ``taler-ios`` (2026-02-14; 2026-02-15) +:Normative references: :doc:`../wallet/wallet-core`, :doc:`../developer/taler-wallet-developer` +:Upstream follow-up: Rename the stale ``TestingGetDiagnosticsOp``/``TestingGetDiagnostics`` API type names to match the public ``getDiagnostics`` operation; keep generated output unchanged here and fix the source generator/types upstream. + Summary ======= @@ -25,12 +35,13 @@ Requirements * Must be easy to use * Must give us relevant information to enable diagnostics -* Must not contain +* Must not contain private keys or unredacted personally identifiable + information Proposed Solution ================= -Wallet-core implements a new ``testingGetDiagnostics`` request. This request +Wallet-core implements a new ``getDiagnostics`` request. This request returns diagnostics information in a JSON format. The export **MUST NOT** contain private keys. IBANs **MUST** be truncated to six characters and user names should be scrubbed or truncated. @@ -52,6 +63,16 @@ Test Plan Since the UI for this is very static, a simple manual test of an export and share/save should be enough. +Definition of Done +================== + +* [x] ``getDiagnostics`` implemented in wallet-core. +* [x] Export/share UI implemented on iOS. +* [ ] Export/share UI implemented on Android and WebExtension. +* [ ] Manual cross-platform export test completed. +* [x] The wallet developer manual documents the privacy/redaction invariants, + not merely the current response fields. + Future Extensions ================= diff --git a/design-documents/083-wallet-initiated-withdrawal.rst b/design-documents/083-wallet-initiated-withdrawal.rst @@ -1,6 +1,13 @@ DD 83: Wallet Initiated Withdrawal ################################## +:Design status: Proposed +:Implementation status: Not started +:DD shepherd: TBD +:Historical contributors: Antoine A +:First published: 2026-02-15 +:Last substantive change: 2026-02-15 + Summary ======= diff --git a/design-documents/084-simple-observability.rst b/design-documents/084-simple-observability.rst @@ -1,6 +1,13 @@ DD 84: Simple observability ########################### +:Design status: Draft +:Implementation status: Not started +:DD shepherd: TBD +:Historical contributors: Antoine A +:First published: 2026-02-16 +:Last substantive change: 2026-02-16 + Summary ======= @@ -45,7 +52,7 @@ All services have a least one REST API. This API should expose a health endpoint // Whether the service is running fine or in a degraded way status: "ok" | "degraded"; // Additional context about the service components and processes - context: [key: string]: string; + context: { [key: string]: string }; } For libeufin-bank: @@ -70,8 +77,8 @@ For libeufin-nexus: "context": { "database": "ok", "ebics-submit": "ok", - "ebics-fetch-latest": "2012-04-23T18:25:43.511Z", - "ebics-fetch-latest-success": "2012-04-23T18:25:43.511Z" + "ebics-submit-latest": "2012-04-23T18:25:43.511Z", + "ebics-submit-latest-success": "2012-04-23T18:25:43.511Z", "ebics-fetch": "failure", "ebics-fetch-latest": "2012-04-23T18:25:43.511Z", "ebics-fetch-latest-success": "2012-03-23T18:25:43.511Z" diff --git a/design-documents/085-transfer-status.rst b/design-documents/085-transfer-status.rst @@ -1,6 +1,13 @@ DD 85: Transfer status ###################### +:Design status: Draft +:Implementation status: Not started +:DD shepherd: TBD +:Historical contributors: Antoine A +:First published: 2026-02-16 +:Last substantive change: 2026-02-16 + Summary ======= @@ -51,7 +58,7 @@ Wire Gateway API **Response:** :http:statuscode:`200 OK`: - JSON object of type `TransferList`. + JSON object of type ``TransferStatusList``. :http:statuscode:`204 No content`: There are no transfers statuses to report (under the given filter). :http:statuscode:`400 Bad request`: @@ -74,7 +81,7 @@ Wire Gateway API interface TransferStatus { // Opaque ID of the status change. - // Is is different from the /transfers + // It is different from the /transfers row_id: SafeUint64; // Opaque ID of the wire transfer initiation performed by the bank. diff --git a/design-documents/086-wallet-design.rst b/design-documents/086-wallet-design.rst @@ -1,6 +1,20 @@ DD 86: Wallet UI Design Proposal ################################ +:Design status: Superseded +:Implementation status: Not started +:DD shepherd: TBD +:Historical contributors: Vlada Svirsh +:First published: 2026-02-22 +:Last substantive change: 2026-02-22 +:Superseded by: DD 87, which incorporates the empty-wallet design into the complete onboarding flow + +.. warning:: + + This proposal was superseded before implementation. DD 87 owns the later + onboarding design; the mockups and navigation below are retained only as + design history. + Summary ======= diff --git a/design-documents/087-wallet-onboarding.rst b/design-documents/087-wallet-onboarding.rst @@ -1,6 +1,14 @@ DD 87: Wallet Onboarding Experience ################################### +:Design status: Accepted +:Implementation status: Partial +:DD shepherd: TBD +:Historical contributors: Vlada Svirsh +:First published: 2026-03-01 +:Last substantive change: 2026-05-18 +:Implementation evidence: ``taler-android`` (2026-03-10; 2026-03-19); ``taler-ios`` (2026-03-10) + Summary ======= This document proposes a design for the wallet onboarding experience. It defines what Android, iOS and WebExtension diff --git a/design-documents/088-wallet-withdraw.rst b/design-documents/088-wallet-withdraw.rst @@ -1,6 +1,14 @@ DD 88: Wallet Withdrawal Experience ################################### +:Design status: Accepted +:Implementation status: Partial +:DD shepherd: TBD +:Historical contributors: Vlada Svirsh +:First published: 2026-03-01 +:Last substantive change: 2026-05-03 +:Implementation evidence: ``taler-android`` (2026-03-04); no corresponding iOS/WebExtension implementation was established + Summary ======= This document describes withdraw flow and experience in wallet. It defines what Android, iOS and WebExtension @@ -95,7 +103,7 @@ Screen contains: - Text: "**Step 2:** Copy this code and paste it into the subject/purpose field in your banking app or website:" - Warning banner (color WarningContainer ``#fdedd3``, rounding radius 15) with warning icon and text: "This is mandatory, otherwise your money will not arrive in this wallet" - Subject to copy and paste -- Text: "**Step 3:** Finish the wire transfer of 11.23 CHF in your banking app or website, then this withdrawal will proceed automatically. Depending on your bank the transfer can take from minutes up to 2 business days. Please be patient." +- Text: "**Step 3:** Finish the wire transfer of **$amount-with-fees** in your banking app or website, then this withdrawal will proceed automatically. Depending on your bank the transfer can take from minutes up to 2 business days. Please be patient." - Secondary button "Share" that opens the system share dialog to share the wire transfer instructions with the banking app Test Plan diff --git a/design-documents/089-merchant-2fa.rst b/design-documents/089-merchant-2fa.rst @@ -1,6 +1,14 @@ DD 89: Merchant 2FA UX ###################### +:Design status: Accepted +:Implementation status: Prototype +:DD shepherd: TBD +:Historical contributors: Florian Dold +:First published: 2026-03-03 +:Last substantive change: 2026-03-03 +:Implementation evidence: ``taler-typescript-core`` (2026-08-05, not merged into the reviewed HEAD) + Summary ======= @@ -83,4 +91,3 @@ Discussion / Q&A * Do we know beforehand from the API which 2FA channels are required? * When signing up, what if the user mistyped their phone number? Do we offer some affordance to go back and edit that information? - diff --git a/design-documents/090-branding.rst b/design-documents/090-branding.rst @@ -1,6 +1,14 @@ DD 90: Branding Guidelines ########################## +:Design status: Accepted +:Implementation status: Prototype +:DD shepherd: TBD +:Historical contributors: Vlada Svirsh +:First published: 2026-03-07 +:Last substantive change: 2026-04-21 +:Implementation evidence: ``taler-typescript-core`` (2026-08-05, not merged into the reviewed HEAD) + Summary ======= This document defines visual and UX guidelines for Taler payment pages/components to give user a consistent experience @@ -89,7 +97,7 @@ visual balance or contrast. .. raw:: html <code>#b4c5ff</code> <div style="display:inline-block;width:14px;height:14px; - background:#b5c5ff;border:1px solid #aaa;margin-left:6px;vertical-align:middle;"></div> + background:#b4c5ff;border:1px solid #aaa;margin-left:6px;vertical-align:middle;"></div> Secondary colors ---------------- @@ -115,7 +123,7 @@ Additional color definitions Detailed color values and any future extensions of the palette are available here: :doc:`Color scheme <066-wallet-color-scheme>`. -..payment-qr +.. _payment-qr: Payment QR code design ~~~~~~~~~~~~~~~~~~~~~~ diff --git a/design-documents/091-wallet-coin-selection.rst b/design-documents/091-wallet-coin-selection.rst @@ -1,6 +1,15 @@ DD 91: Wallet Coin Selection ############################ +:Design status: Accepted +:Implementation status: Implemented +:DD shepherd: TBD +:Historical contributors: Florian Dold +:First published: 2026-03-20 +:Last substantive change: 2026-03-20 +:Implementation evidence: ``taler-typescript-core`` (2026-08-10) +:Normative references: :doc:`../developer/taler-wallet-developer` + Summary ======= diff --git a/design-documents/092-incremental-backup-sync.rst b/design-documents/092-incremental-backup-sync.rst @@ -2,6 +2,15 @@ DD 92: Incremental Wallet Backup and Sync =========================================== +:Design status: Accepted +:Implementation status: Prototype +:DD shepherd: TBD +:Historical contributors: Iván Ávalos, Christian Grothoff +:First published: 2026-03-26 +:Last substantive change: 2026-08-18 +:Implementation evidence: ``taler-typescript-core`` (2026-08-12); ``taler-android`` (2026-08-07; 2026-08-09); not merged into the reviewed HEADs +:Normative references: ``core/api-sync.rst`` (vBACKUP is upcoming; the current v2 API says no component uses Sync) + Summary ======= @@ -2870,6 +2879,10 @@ assumption already made in the :ref:`threat-model`. Definition of done ================== +The checked implementation items below describe prototype feature branches, +not the reviewed main branches. The normative Sync API still labels backup +support as upcoming. + * [x] Design backup schema. * [ ] Design incremental sync. * [x] Design backup/restore schedules. diff --git a/design-documents/093-checkout-page.rst b/design-documents/093-checkout-page.rst @@ -1,6 +1,13 @@ DD 93: Checkout Page #################### +:Design status: Draft +:Implementation status: Not started +:DD shepherd: TBD +:Historical contributors: Vlada Svirsh +:First published: 2026-04-21 +:Last substantive change: 2026-06-24 + Summary ======= The checkout page may be reached from different places, such as a merchant portal or another service integrating @@ -36,14 +43,15 @@ layout on mobile. At the top of the page, the user sees the Taler heading and a short instruction to scan the QR code with a mobile wallet. The main content area contains: -* the `QR code <https://docs.taler.net/design-documents/090-branding.html#payment-qr-code-design>`_ -* Payment deadline as "QR code is available far payment until ``$date``, ``$time`` +* the :ref:`payment QR code <payment-qr>` +* Payment deadline as "QR code is available for payment until ``$date``, ``$time``" * the main order metadata next to it * the primary action button to open the Taler wallet * a secondary link for users who do not yet have a wallet * a footer with a link to the GNU Taler website and copyright information -The order metadata must always show the order id, summary, amount, and merchant name, if these fields are available. +When available, the order metadata must show the order ID, summary, amount, +and merchant name. Order with discounts or subscriptions ------------------------------------- @@ -101,4 +109,4 @@ elements should be: * footer The QR code container, action button, and order details should use full available width with appropriate -spacing for touch interaction and readability. -\ No newline at end of file +spacing for touch interaction and readability. diff --git a/design-documents/094-discounts-passes-wallet.rst b/design-documents/094-discounts-passes-wallet.rst @@ -1,6 +1,14 @@ DD 94: Discounts & Passes Wallet UI ################################### +:Design status: Accepted +:Implementation status: Partial +:DD shepherd: TBD +:Historical contributors: Vlada Svirsh +:First published: 2026-04-29 +:Last substantive change: 2026-05-29 +:Implementation evidence: ``taler-ios`` (2026-06-22; 2026-06-24); ``taler-typescript-core`` (2026-08-11, not merged into the reviewed HEAD) + Summary ======= @@ -10,7 +18,10 @@ way to present, manage, and display these entities across the wallet, including Motivation ========== -Merchants can provide users with discounts or passes that apply to specific products or services. The wallet must support: +Merchants can provide users with discounts or passes that apply to specific +products or services. In protocol terminology, a user-facing "pass" is a token +family of kind ``subscription``; ``pass`` is not a separate token-family kind. +The wallet must support: * Clear presentation of available discounts and passes * Ability for users to review and apply them during checkout @@ -155,4 +166,3 @@ Drawbacks Discussion / Q&A ================ - diff --git a/design-documents/095-captcha-100.rst b/design-documents/095-captcha-100.rst @@ -1,6 +1,15 @@ DD 95: Captcha 100 ################## +:Design status: Proposed +:Implementation status: Partial +:DD shepherd: TBD +:Historical contributors: Christian Grothoff, Bohdan Potuzhnyi +:First published: 2026-06-16 +:Last substantive change: 2026-06-16 +:Implementation evidence: ``paivana`` (2026-04-19); Pepsi, wire-void, and complete CAPTCHA deployment evidence was not established +:Normative references: ``taler-paivana-manual.rst`` and ``frags/paivana-httpd-manual.rst`` + Summary ======= @@ -19,15 +28,12 @@ filters or to solve Captcha's. In this context, forcing the sender to make a Taler deposit becomes simply another form of imposing a cost, and one that would cost an attacker more dearly. -We can quickly enable this use-case by setting the Taler fees to 100%. At -this point, the "merchant" never actually receives any money (and customers -that withdrew tokens cannot get money when they return them either), so the -operator would not be a payment service as they do not give money to anybody. -While this is less attractive to the recipient, it would still be effective at -blocking bots. At the same time, this model can be rolled out globally pretty -quickly because at 100% fees we do not need a money transmitter or e-money -issuer license, as we no longer transmit money -- we only accept money in -return for a digital service, like many other regular unregulated businesses. +We can investigate this use-case by setting the Taler fees to 100%. At this +point, the "merchant" never actually receives any money (and customers that +withdrew tokens cannot get money when they return them either), while the fee +still imposes a cost on bots. Whether such an operator is outside payment- +service, money-transmitter, or e-money licensing is jurisdiction-dependent and +requires qualified legal review; this design makes no global licensing claim. Motivation ========== @@ -132,4 +138,3 @@ Drawbacks Discussion / Q&A ================ - diff --git a/design-documents/096-partial-payments.rst b/design-documents/096-partial-payments.rst @@ -1,6 +1,15 @@ DD 96: Partial Payments ####################### +:Design status: Proposed +:Implementation status: Partial +:DD shepherd: TBD +:Historical contributors: Bohdan Potuzhnyi +:First published: 2026-06-22 +:Last substantive change: 2026-08-18 +:Implementation evidence: ``merchant`` (2026-07-20, not merged into the reviewed HEAD); ``taler-typescript-core`` (2026-08-19) +:Normative references: ``core/api-merchant.rst`` (upcoming ``vMixedPayments`` and associated endpoint schemas) + Summary ======= @@ -47,8 +56,8 @@ Requirements payments before the Taler payment. * The Taler payment is always the last payment step. * If the Taler payment fails after other payments succeeded, the POS must - either modify the order and retry the Taler step or refund the already - completed non-Taler payments. + either abandon the old order, create a replacement order with an adjusted + split, and retry the Taler step, or refund the completed non-Taler payments. * Orders with settled external payments and a failed Taler payment must remain visible to merchant-facing applications. They must not be deleted by normal order deletion or by accident. @@ -326,9 +335,11 @@ payment method. The POS or integrating application must therefore choose one of these recovery paths: -* modify the order payment split and retry the Taler payment; +* abandon the old order, create a replacement with a modified payment split, + and retry the Taler payment; * cancel the order and refund or void the completed non-Taler payments; -* proceed with different payment method, and make Taler part lower or zero. +* create a replacement order using a different payment method, with the Taler + part lower or zero. Until one of these recovery paths is completed, the order must remain visible to merchant-facing applications. No dedicated order status value is diff --git a/design-documents/097-challenge-confirmations.rst b/design-documents/097-challenge-confirmations.rst @@ -3,6 +3,15 @@ DD 97: Challenge-Signature Payment Confirmations ################################################ +:Design status: Draft +:Implementation status: Partial +:DD shepherd: TBD +:Historical contributors: Bohdan Potuzhnyi +:First published: 2026-07-23 +:Last substantive change: 2026-07-23 +:Implementation evidence: ``exchange`` (2026-08-01); ``merchant`` (2026-08-02, not merged into the reviewed HEAD) +:Normative references: ``core/api-merchant.rst`` (upcoming version) and ``core/merchant/post-orders-ORDER_ID-pay.rst`` + Summary ======= @@ -75,8 +84,9 @@ in the offline verifier. The private key is never exposed through the API. For these algorithms, the client supplies a fresh 32-byte challenge while instantiating a template. The challenge is encoded using Crockford Base32 and becomes part of the order. After successful payment, the backend signs -the challenge with the key associated with the template's OTP device. The -signature is returned in ``PaymentResponse.pos_confirmation``. +the protocol-defined hash of the challenge with the key associated with the +template's OTP device. The signature is returned in +``PaymentResponse.pos_confirmation``. The wallet only transports the challenge to the merchant and the resulting signature back to the device. It does not possess the signing key and does @@ -152,7 +162,7 @@ Payment Response For a challenge-signature OTP device, the existing ``PaymentResponse.pos_confirmation`` field contains the Crockford Base32 -encoded signature over the order's challenge. +encoded signature over the protocol-defined hash of the order's challenge. Error Handling ============== diff --git a/design-documents/098-token-fountains.rst b/design-documents/098-token-fountains.rst @@ -3,6 +3,14 @@ DD 98: Token Fountains for Promotions ##################################### +:Design status: Draft +:Implementation status: Not started +:DD shepherd: TBD +:Historical contributors: Bohdan Potuzhnyi +:First published: 2026-07-23 +:Last substantive change: 2026-07-24 +:Normative references: ``core/api-merchant.rst`` (upcoming token-fountain API) + Summary ======= diff --git a/design-documents/099-programmable-templates.rst b/design-documents/099-programmable-templates.rst @@ -3,6 +3,13 @@ DD 99: Programmable Template Validation ####################################### +:Design status: Draft +:Implementation status: Not started +:DD shepherd: TBD +:Historical contributors: Bohdan Potuzhnyi +:First published: 2026-07-23 +:Last substantive change: 2026-07-23 + Summary ======= diff --git a/design-documents/100-shares.rst b/design-documents/100-shares.rst @@ -1,6 +1,13 @@ DD 100: Share Tokenization ########################## +:Design status: Draft +:Implementation status: Not started +:DD shepherd: TBD +:Historical contributors: Christian Grothoff +:First published: 2026-08-09 +:Last substantive change: 2026-08-18 + Summary ======= @@ -56,6 +63,11 @@ the cryptographic part: we probably want these announcements to be managed by the merchant backend as a new feature: this way, all of the auditing can focus just on the merchant backend + +Notification endpoint ownership is therefore an open design decision: the +initial frontend-owned proposal and the merchant-backend alternative above +must be resolved before the API is specified. + - new frontend includes its own wallet; it is used to pay dividends; wallets can request a contract to sell generation X shares for generation X+1 shares (once a notification has been posted that diff --git a/design-documents/101-semantic-token-families.rst b/design-documents/101-semantic-token-families.rst @@ -1,9 +1,14 @@ DD 101: Semantic Token Families MVP ################################### -:Status: Experimental +:Design status: Experimental +:Implementation status: Prototype :DD shepherd: Florian Dold +:Historical contributors: Florian Dold :First published: 2026-08-13 +:Last substantive change: 2026-08-19 +:Implementation evidence: ``taler-typescript-core`` (2026-08-13, not merged into the reviewed HEAD) +:Normative references: ``core/merchant/post-private-tokenfamilies.rst`` currently specifies only opaque ``extra_data``; the semantic schemas remain experimental Summary ======= @@ -37,7 +42,9 @@ Proposed Solution Schema ------ -The semantic object is stored under the key matching the token family's kind. +The semantic object is stored under an experimental top-level key corresponding +to the token family's kind (``experimental_subscription`` or +``experimental_discount``). These interfaces show the semantic members of ``extra_data``; the object may also contain unrelated top-level members. @@ -246,9 +253,12 @@ tokens on paid orders and later redeems the configured threshold. Definition of Done ================== -The editor, order and PoS flows implement the rules above; documentation and -translations are updated; unit, UI, catalog, type, lint, and harness integration -checks pass. Until then, the metadata remains explicitly experimental. +* [x] Prototype editor, order and PoS flows exist on a feature branch. +* [ ] Prototype merged into the main branch. +* [ ] Documentation and translations updated. +* [ ] Unit, UI, catalog, type, lint, and harness integration checks pass. + +Until all items are complete, the metadata remains explicitly experimental. Alternatives ============ diff --git a/design-documents/999-template.rst b/design-documents/999-template.rst @@ -1,6 +1,37 @@ DD XY: Template ############### +:Design status: Draft +:Implementation status: Not started +:DD shepherd: NAME or TBD +:Historical contributors: NAME(S) or TBD +:First published: YYYY-MM-DD +:Last substantive change: YYYY-MM-DD + +Every numbered design document must carry all six fields above. Keep design +maturity separate from implementation progress: + +* ``Design status`` is one of ``Draft``, ``Proposed``, ``Accepted``, + ``Experimental``, ``Superseded``, ``Rejected``, or ``Abandoned``. +* ``Implementation status`` is one of ``Not started``, ``Prototype``, + ``Partial``, ``Implemented``, ``Removed``, ``Unknown``, or ``N/A``. + +Use ``DD shepherd: TBD`` rather than omitting ownership. List people who made +historically substantive contributions, not authors of purely mechanical +changes. ``First published`` is the date the DD first appeared, while ``Last +substantive change`` excludes formatting-only changes. + +Add the following fields when applicable: + +* ``Implementation evidence`` using repository names and ISO dates for + auditable landing evidence. Do not include commit hashes. State explicitly + when cited work is not merged into the reviewed main branch. +* ``Superseded by`` when the design status is ``Superseded``. +* ``Normative references`` for current API specifications or reference + manuals. A DD is not itself a normative API specification. +* ``Upstream follow-up`` when a verified correction belongs in generated or + externally maintained documentation and must not be made in this repository. + Summary ======= diff --git a/design-documents/README.rst b/design-documents/README.rst @@ -0,0 +1,84 @@ +Design document lifecycle +######################### + +Design documents record why a change was considered and how its design +evolved. They are not the normative specification after a design has been +implemented. Implemented protocol behavior belongs in the API specification; +implementation, deployment, and operational behavior belongs in the +corresponding reference manual. + +Required metadata +================= + +Every numbered design document must begin with these fields: + +``Design status`` + The state of the design decision. The allowed values are ``Draft``, + ``Proposed``, ``Accepted``, ``Experimental``, ``Superseded``, ``Rejected``, + and ``Abandoned``. + +``Implementation status`` + The state of the described implementation. The allowed values are ``Not + started``, ``Prototype``, ``Partial``, ``Implemented``, ``Removed``, + ``Unknown``, and ``N/A``. + +``DD shepherd`` + The person currently responsible for moving the design forward and keeping + its status accurate. Use ``TBD`` when no current shepherd has agreed to + take responsibility; historical authorship is not an assignment of current + ownership. + +``Historical contributors`` + The people who made substantive contributions to the design text. Do not + include authors of repository-wide formatting-only changes. + +``First published`` + The ISO date of the first commit containing substantive content for this DD. + Copied template or predecessor-file history does not count. + +``Last substantive change`` + The ISO date of the newest commit that changed the design's meaning. Pure + spelling, formatting, build, or title-normalization changes do not count. + +The following fields are added when applicable: + +``Implementation evidence`` + Repositories and ISO dates that establish a prototype, landing, completion, + or removal. Work that is present only on a feature branch must be identified + as such and has implementation status ``Prototype``. + +``Superseded by`` + The successor design or normative specification. + +``Normative references`` + The API specifications and reference manuals that now own the implemented + behavior. + +``Upstream follow-up`` + A discrepancy whose authoritative source is generated by, or maintained in, + another repository. Generated files in this repository must not be edited + by hand. + +Interpreting lifecycle states +============================= + +The two status fields are deliberately independent. For example, a design +can be ``Superseded`` while its historical implementation remains +``Implemented``. A feature that has substantial implementation only on a +non-main branch is a ``Prototype``, not ``Partial`` or ``Implemented``. +Policy documents use ``N/A`` unless they define measurable software or +platform deliverables. + +Titles beginning with ``XX`` are a legacy visual marker for deprecated design +documents. They are retained for historical continuity, but the metadata +fields are authoritative. + +Maintaining design documents +============================ + +When a feature lands, update its implementation status and evidence, check +only Definition-of-Done items supported by repository or API evidence, and add +the normative references. Preserve useful historical discussion, but place a +prominent note before stale material so readers do not mistake it for current +behavior. Unresolved product, security, or legal questions must remain +explicit instead of being silently resolved from implementation accidents. diff --git a/design-documents/index.rst b/design-documents/index.rst @@ -2,16 +2,18 @@ Design Documents ################ This is a collection of design documents related to GNU Taler. -The goal of these documents is to discuss facilitate discussion around -new features while keeping track of the evolution of the whole system -and protocol. +The goal of these documents is to facilitate discussion about new features +while keeping track of the evolution of the whole system and protocol. -Design documents that start with "XX" are considered deprecated. +Design documents that start with "XX" use a legacy marker for deprecated +documents. The lifecycle metadata in each document is authoritative. See +:doc:`README` for the status vocabulary and maintenance rules. .. toctree:: :maxdepth: 1 :glob: + README 001-new-browser-integration 002-wallet-exchange-management 003-tos-rendering @@ -111,5 +113,6 @@ Design documents that start with "XX" are considered deprecated. 097-challenge-confirmations 098-token-fountains 099-programmable-templates + 100-shares 101-semantic-token-families 999-template diff --git a/developer/taler-developer-manual.rst b/developer/taler-developer-manual.rst @@ -690,7 +690,7 @@ prepared. Database schema versioning -------------------------- -The PostgreSQL databases of the exchange and the auditor are versioned. +The PostgreSQL databases of the exchange, auditor, and merchant are versioned. See the ``versioning.sql`` file in the respective directory for documentation. Every set of changes to the database schema must be stored in a new @@ -701,6 +701,13 @@ environment), existing scripts MUST be immutable. Developers and operators MUST NOT make changes to database schema outside of this versioning. All tables of a GNU Taler component should live in their own schema. +Runtime stored procedures are loaded from the component's generated +``procedures.sql`` after schema patches. Updating a runtime procedure does +not itself advance the schema-patch version; table, index, constraint, and +data migrations still require a new numbered script. Component database +initialization tools are the supported way to apply both the pending patches +and the current procedure definitions. + QA Plans ======== @@ -739,6 +746,24 @@ Tag releases with an **annotated** commit, like $ git tag -a v0.1.0 -m "Official release v0.1.0" $ git push origin v0.1.0 +Prebuilt artifact policy +------------------------ + +Prebuilt artifacts are stored separately from source, normally on an orphan +``prebuilt`` branch, and are consumed through a Git submodule pinned to an +exact commit. Projects producing such artifacts MUST provide repeatable +Makefile targets that build the artifact, prepare the prebuilt worktree, and +install the result in that worktree. A consumer's ``bootstrap`` script MUST +initialize the submodule and SHOULD fail gracefully when an obsolete prebuilt +commit is no longer available. + +Artifacts use the layout ``COMPONENT/VERSION/``. ``VERSION`` MUST match both +the component version and a source tag. Every revision intended for consumers +MUST have a ``prebuilt-SERIAL`` tag; a ``COMPONENT/VERSION`` tag MAY additionally +identify the component-specific payload. Consumers MUST pin a tagged commit +and SHOULD use sparse checkout. Source, build instructions, and dependency +versions must remain sufficient to reproduce the artifact offline. + Database for tests ------------------ @@ -890,6 +915,39 @@ for that. There is also the possibility to trigger builds manually, but this is only reserved to "admin" users. +Each repository owns its CI definition under ``contrib/ci``. Jobs are +directories named ``contrib/ci/jobs/N-NAME`` and MUST contain ``job.sh``; +their numeric prefix determines execution order. Optional job configuration +is stored as ``config.ini``. Unless every job selects its own container, the +repository MUST provide ``contrib/ci/Containerfile``. Projects SHOULD provide +at least separate build and test jobs. + +The repository's ``contrib/ci/ci.sh NAME`` entry point runs an individual job +locally in the same containerized environment used by Buildbot. CI behavior +belongs in the component repository rather than in a central Buildbot-only +configuration. Cross-repository pipelines are separate builders because they +require several source trees and have different triggering requirements. + + +Dynamic form metadata +===================== + +Taler Web UIs that consume backend-provided form descriptions use a versioned +``FormMetadata`` envelope. It contains a stable form ``id``, human-readable +``label`` and optional ``description``, numeric ``version``, and a ``config`` +object. JSON configurations use one of two layouts: + +* ``single-column`` with an ordered ``fields`` list; or +* ``double-column`` with an ordered ``sections`` list, where each section has a + title, optional description, and fields. + +Fields are discriminated by their ``type``. Currently supported field classes +include amount, boolean, date, duration, one- and multi-select, text, +multi-line text, and toggle controls. Consumers MUST reject unknown or +malformed structures through the shared codec instead of interpreting them as +arbitrary HTML. The version belongs to the form definition and must change +when an incompatible metadata interpretation is introduced. + Internationalisation ==================== @@ -900,6 +958,14 @@ translated strings. .. include:: dictionary.rst +iOS localization uses the checked-in ``Localizable.xcstrings`` catalogs as the +application source and checked-in ``XLIFF/*.xliff`` files as the Weblate +interchange representation. The XLIFF ``original`` attributes identify the +source ``.xcstrings`` catalogs. Translation updates must round-trip through +Xcode's XLIFF import/export support, preserve message identifiers and +placeholders, and be followed by a full application build. The older proposed +``pogen`` conversion through PO files is not the deployed iOS workflow. + iOS Apps ======== diff --git a/developer/taler-wallet-developer.rst b/developer/taler-wallet-developer.rst @@ -560,6 +560,174 @@ The integration tests are run via the ``taler-harness`` tool. taler-harness run-integrationtests +Transaction lifecycle contract +============================== + +Wallet transactions expose their current state, user-visible information, and +permitted ``txActions`` through the wallet API. UIs MUST derive buttons from +``txActions`` rather than infer them from a locally duplicated transition +table. The common lifecycle classes are: + +* ``pending`` and ``finalizing``: wallet processing is active; +* ``dialog``: an explicit user decision is required; +* ``suspended``: processing was paused and may offer resume or deletion; +* ``aborting``: compensating/refund work is active; +* ``done``: the intended operation completed; +* ``failed`` or ``aborted``: processing ended unsuccessfully, with the reason + carried by the transaction response; and +* ``deleted``: the history entry is hidden, while cryptographic records still + needed for spend, recoup, or auditing may remain. + +Network retries and internal self-transitions need not change the lifecycle +class. An implementation can expose error details while remaining pending. +Deletion is not cancellation: a transaction must first use an offered abort +action when protocol-side compensation is necessary. + + +KYC-gated operation retry +========================= + +Withdrawals, deposits, and peer-to-peer operations use one common retry +algorithm when an exchange denies progress for KYC or AML reasons: + +#. Attempt the operation unless the most recent denial is less than one hour + old. Success ends processing; HTTP 451 records the denial and whether the + account authorization was invalid; unrelated failures back off. +#. Query the operation's ``/kyc-check/`` endpoint. The first request does not + long-poll. Later requests long-poll for account authorization, rule, or AML + changes and include ``min_rule`` when a rule generation is known. +#. Compare the HTTP status, Taler error code, and rule generation with the + previous response. An unchanged response backs off. HTTP 200 or 204 + retries the operation; HTTP 202 evaluates the exposed limits; HTTP 403 can + switch to a requested account key when the wallet owns it; HTTP 404 either + requests new authorization or evaluates default limits. +#. A ``verboten`` limit permanently fails the transaction. A time-window + limit schedules the next attempt for the first permitted time. Otherwise + the wallet immediately retries the operation. + +Manual review of KYC instructions, a new authorization transfer, or relevant +progress in another operation resets the retry delay. Repeated network +timeouts still use exponential backoff even when the HTTP long-poll duration +is shortened to fit middleware limits. + + +Exchange base-URL migration +=========================== + +Wallet-core maintains explicit ``old URL -> new URL`` migration plans. A plan +is applied only after the old exchange is unavailable or reports a mismatching +canonical ``base_url`` and the new URL returns a valid ``/keys`` response whose +``base_url`` matches that new URL. Applying a plan atomically replaces stored +references and records the old URL, new URL, and migration timestamp. + +Operators must publish wallet support before moving the exchange, allow a +client-update grace period, migrate the database and optional security-module +keys, and keep a reverse proxy from the old URL for at least the validity of +the last old ``/keys`` response. Merchants must configure the new URL +explicitly; wallet migration plans do not rewrite merchant configuration. + + +IBAN and BBAN presentation +========================== + +The wallet API converts between the protocol's ``payto://iban`` representation +and a user-facing account field. ``convertIbanAccountFieldToPayto`` accepts an +IBAN or the currency's supported BBAN form and returns the normalized payto +URI plus the detected entry type. ``convertIbanPaytoToAccountField`` performs +the reverse conversion. Deposit wire types advertise ``preferredEntryType`` +so UIs do not maintain a separate currency table. + +HUF accounts use BBAN entry/display for production ``iban`` wire targets. The +CHF BBAN mapping is reserved for the wallet development experiment. A BBAN +field must also accept a pasted full IBAN. Protocol messages continue to use +the normalized payto URI; BBAN is a presentation and entry convention only. + + +Diagnostics export privacy +========================== + +``getDiagnostics`` produces support information suitable for saving or +sharing without exporting the wallet database. The response MUST NOT contain +private keys or other secret key material. Account identifiers such as IBANs +must be truncated to at most six characters, and user names or equivalent +identifiers must be removed or truncated. Adding fields to the response +requires a privacy review against these invariants. The diagnostics action is +available outside developer mode because it is the preferred alternative to a +database export. + + +Coin selection +============== + +For one exchange, wallet-core selects eligible coins as follows: + +#. Traverse denominations from smallest to largest and add coins until their + value covers the target, using the earliest-expiring coins first within a + denomination. +#. Traverse selected denominations from largest to smallest and remove coins + whenever the remainder still covers the target. Obtain change from the + smallest indispensable coin when needed. +#. When customer-paid fees remain above the merchant allowance and the wallet + is not imbalanced, replace groups of small coins with equivalent larger + coins until fees fall below the allowance or no useful replacement exists. + +A wallet is considered imbalanced for this step when it holds, on average, +more than five times the denomination ratio in coins per denomination, +excluding the largest denomination. This keeps selection linear, spends old +coins first, and limits small-coin accumulation. Multiple-exchange selection +is outside this algorithm and must be handled by a higher-level decision. + + +Wallet color roles +================== + +Wallet UIs use semantic theme roles instead of literal colors in components. +Use roles such as ``primary`` and ``onPrimary`` for an accent and its +foreground, the corresponding ``Container`` pair for filled surfaces, and +``error``, ``warning``, and ``success`` roles for feedback. Surface, +background, outline, and foreground roles must likewise be paired by meaning; +do not choose a role merely because its current hex value looks suitable. + +Every component must obtain roles from the platform theme so light and dark +modes can switch without component-specific branches. New role pairs and +overrides require WCAG 2.1 AA contrast verification in both modes, including +disabled, selected, focused, and error states. Native and WebExtension +implementations may encode themes differently, but should retain the same +semantic names and intended hierarchy. The evolving palette and adoption +status are recorded in :doc:`../design-documents/066-wallet-color-scheme`. + + +Wallet database migrations +========================== + +Wallet database upgrades are automatic and must preserve the previous data +until the new representation is known to be usable. The browser wallet uses +an IndexedDB metadata database to identify the active major database and a +separately named major-version database for wallet records. This indirection +allows a major migration to build a new database without destroying the old +one first. + +IndexedDB changes use three mechanisms: + +* A major migration creates a new major-version database and explicitly moves + data. This is reserved for changes that cannot be expressed safely in an + IndexedDB upgrade transaction; a backup export/import cycle is preferred + when practical. +* A minor schema migration adds or removes object stores or indexes by + changing the schema declaration and its ``versionAdded`` metadata. +* An ordered fixup transforms stored values, such as when a mandatory field or + serialized representation changes. Fixups can also repair data written by + an already deployed buggy version. + +The native SQLite backend has its own ordered schema migrations. Migration +from the IndexedDB emulation to native SQLite is a separate, explicit path; +backend versions must not be inferred to be interchangeable. Every migration +needs tests starting from representative old data, including interrupted and +retry scenarios. Current schema declarations and fixup registries in +wallet-core are authoritative; the design history is in +:doc:`../design-documents/034-wallet-db-migration`. + + Dev Experiments =============== diff --git a/index.rst b/index.rst @@ -110,6 +110,7 @@ and overall usage of the different Taler components in text and video formats. :caption: For Developers core/index + wallet/index developer/index design-documents/index diff --git a/libeufin/bank-manual.rst b/libeufin/bank-manual.rst @@ -122,6 +122,30 @@ Configuring multi-factor authentication libeufin-bank supports two-factor authentication. libeufin-bank uses helper scripts to send challenge codes to addresses for multi-factor authentication. We provide two default helper scripts: ``libeufin-tan-email.sh`` to send e-mails and ``libeufin-tan-sms.sh`` to send SMS. To enable two-factor authentication you need to configure at least one TAN channel. +Authentication lockout and throttling +++++++++++++++++++++++++++++++++++++++ + +Password authentication is used to obtain access tokens; normal Core Bank API +operations use those tokens. A wrong password by itself does not lock an +account, because usernames are public and that policy would let an attacker +lock out another user. Deployments must rate-limit the token-creation endpoint +at the ingress layer to bound password-hashing work. + +For an account protected by multi-factor authentication, repeated failed +confirmation of token-creation challenges can lock creation of new tokens. +Existing tokens remain usable. An authenticated user with an existing token +can recover by changing the password; otherwise an administrator must set a +new password. Clients can observe the account's ``locked`` status and the +token endpoint reports ``TALER_EC_BANK_ACCOUNT_LOCKED``. + +The bank permits concurrent challenges for use on multiple devices, but caps +the number of pending challenges per account as well as retransmissions and +confirmation attempts. Challenge hints must not expose a complete email +address or telephone number. Operators must still throttle challenge +creation and delivery at the ingress layer to protect external SMS and mail +services. The exact endpoint responses are specified by the +:doc:`../core/api-corebank`. + SMS TAN channel +++++++++++++++ diff --git a/libeufin/nexus-manual.rst b/libeufin/nexus-manual.rst @@ -326,6 +326,29 @@ can be ignored. This implies that the actual balance of your bank account may de To fix this, you must periodically send administrative balance adjustment transfers containing "ADMIN BALANCE ADJUST" in their subject. +Transaction identity +==================== + +Incoming ISO 20022 transactions do not have one universally available unique +identifier. Nexus therefore stores the three identifiers independently: + +``uetr`` + The ISO 20022 Unique End-to-end Transaction Reference, represented as a UUID. + +``tx_id`` + The ISO 20022 transaction identifier supplied under ``TxId``. + +``acct_svcr_ref`` + The account-servicing institution's reference for the booked entry. + +Each value is optional because banks and message variants expose different +subsets, but an incoming credit must contain at least one. When one identifier +is needed for display or correlation, Nexus prefers ``uetr``, then ``tx_id``, +then ``acct_svcr_ref``. Import and deduplication must retain all identifiers +that arrive later instead of collapsing them into one synthetic database +column. Outgoing transactions use their end-to-end ID and may additionally +gain an account-servicer reference after booking. + Manual submission acknowledgement ================================= diff --git a/taler-exchange-manual.rst b/taler-exchange-manual.rst @@ -275,7 +275,7 @@ The exchange process MUST thus be in the same group as the crypto helper processes to enable access to the keys. No other users should be in that group! -The two helper processes will create the required private keys, and allow +The three helper processes will create the required private keys, and allow anyone with access to the UNIX domain socket to sign arbitrary messages with the keys or to inform them about a key being revoked. The helper processes are also responsible for deleting the private keys if their validity period @@ -753,7 +753,9 @@ must then have the following options: primes) have for this type of coin. - ``AGE_RESTRICTED``: Set to ``YES`` to make this a denomination with support - for age restrictions. See age restriction extension below for details. + for age restrictions. See the age-restriction documentation below for + details. Age restriction is a protocol feature; it no longer uses the + retired generic extension mechanism described by DD06. This option is optional and defaults to ``NO``. See :doc:`manpages/taler-exchange.conf.5` for information on *duration* values diff --git a/taler-merchant-manual.rst b/taler-merchant-manual.rst @@ -782,7 +782,7 @@ should return some basic configuration status data about the service. Please note that your backend might then be globally reachable without any access control. You can either: - * Use the ``--auth=$TOKEN`` command-line option to **taler-merchant-httpd** to set an access token to be provided in an ``Authorize: Bearer $TOKEN`` HTTP header. Note that this can be used at anytime to override access control, but remains only in effect until a first instance is created or an existing instance authentication setting is modified. + * Use the ``--auth=$TOKEN`` command-line option to **taler-merchant-httpd** to set an access token to be provided in an ``Authorization: Bearer $TOKEN`` HTTP header. Note that this can be used at anytime to override access control, but remains only in effect until a first instance is created or an existing instance authentication setting is modified. * Set the ``TALER_MERCHANT_TOKEN`` environment variable to ``$TOKEN`` for the same effect. This method has the advantage of ``$TOKEN`` not being visible as a command-line interface to other local users on the same machine. * Set up an instance with an authentication token before some unauthorized person has a chance to access the backend. As the backend is useless without any instance and the chances of remote attackers during the initial configuration is low, this is probably sufficient for most use-cases. Still, keep the first two scenarios in mind in case you ever forget your access token! @@ -1782,6 +1782,58 @@ The database scheme used by the merchant looks as follows: .. image:: images/merchant-db.png +Schema migrations and stored procedures +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Merchant schema changes are delivered as contiguously numbered SQL patches +and tracked through the shared ``versioning.sql`` mechanism. Once a patch has +been part of a release or deployed to production or staging, it is immutable; +a correction requires another patch. The merchant does not use the +exchange's partition/shard master-table scheme. + +Runtime functions and procedures are collected in the generated +``procedures.sql`` and loaded after the numbered schema patches. Changing a +runtime procedure therefore does not alter the schema-patch version. Table, +index, constraint, or stored-data changes still require a numbered patch. +Developers must update the procedure sources and regenerate the aggregate +rather than editing an installed database or generated output directly. +``taler-merchant-dbinit`` is the supported installation and upgrade path. + +Statistics storage and operation +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Merchant statistics are maintained transactionally by database triggers, so +the statistics endpoints return current values rather than a periodically +computed snapshot. Amount-valued statistics are separated by currency. +Operators can query amount and counter slugs as bucketed values, sliding +intervals, or both through the ``statistics-read`` API endpoints documented in +the Merchant API. + +Bucket metadata defines calendar ranges and the number of generations to +retain. Interval metadata defines monotonically increasing windows and their +precision. Old event slots may be coarsened to the precision of a larger +window and are eventually removed by statistics garbage collection. A +missing old value can therefore mean that the deployment does not retain that +granularity; clients must handle the API's ``410 Gone`` response. + +Developers adding a built-in statistic use the database procedures +``bump_number_bucket_stat``, ``bump_amount_bucket_stat``, +``bump_number_interval_stat``, ``bump_amount_interval_stat``, +``bump_number_stat``, and ``bump_amount_stat`` rather than updating statistics +tables directly. Reads of sliding intervals go through +``statistic_interval_number_get`` or ``statistic_interval_amount_get`` so that +expiry and coarsening are applied consistently. ``statistic_bucket_gc`` +removes expired buckets and event slots. + +Statistics schema changes follow the ordinary merchant database versioning +and are installed or upgraded by ``taler-merchant-dbinit``. Operators must not +modify the core statistics tables or triggers outside that versioning process. + +Periodic report scheduling is a separate layer: configured report generators +consume the stored statistics through the report APIs. Operators must +configure the generator section before scheduling it; an unconfigured program +is reported as ``501 Not Implemented``. + .. _MerchantBenchmarking: Benchmarking diff --git a/wallet/browser-integration.rst b/wallet/browser-integration.rst @@ -0,0 +1,103 @@ +.. + This file is part of GNU TALER. + Copyright (C) 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 + Foundation; either version 3.0, or (at your option) any later version. + +Wallet Browser Integration Manual +################################# + +Websites can advertise Taler actions and explicitly request browser-wallet +features without depending on a particular extension identifier. All page +integrations are subject to the wallet user's preferences. Websites must +retain an ordinary Taler link or another fallback because extension injection +and link interception are not available in every browser or navigation path. + +Advertising a Taler action +========================== + +A page can advertise a wallet action in its document head: + +.. code:: html + + <meta name="taler-uri" content="taler://withdraw/bank.example/operation-id"> + +The extension validates the URI before opening or presenting it. The first +``taler-uri`` element in document order is the page's advertised action; an +invalid first element is not skipped in favor of a later element. Ordinary +Taler links are handled separately when activated. + +When automatic opening is disabled, the extension can expose the current +page's validated action through its popup. Metadata inserted, removed, or +changed in the document head is observed; the page body is not scanned. + +Requesting browser-wallet features +================================== + +Additional features are requested with a comma-separated list: + +.. code:: html + + <meta name="taler-support" content="uri, callback, api"> + +Tokens are trimmed and compared case-insensitively. Unknown tokens are +ignored. Each known feature is independently controlled by the user's wallet +settings: + +``uri`` + Handle a primary-button activation of a link whose ``href`` is a recognized + Taler action. Pages must retain the Taler URI in ``href`` so that native + handlers and copy-link behavior remain available. + +``callback`` + If ``window.talerCallback`` is a function, call it with + ``{present: true}`` when the WebExtension becomes available. Callback + execution is best-effort. A page must not rely on receiving a later + ``present: false`` notification. + +``api`` + Inject the legacy-compatible ``window.taler`` object asynchronously. A + compatibility integration that needs to detect injection should also + request ``callback`` and wait for it. The object currently has no supported + callable methods; new integrations should use ``taler-uri``, the ``uri`` + feature, and ``talerCallback`` instead. + +Without ``taler-support``, the page receives no callback or API and its links +are not intercepted. Advertising an action with ``taler-uri`` remains +independent of these requested features. + +The page API +============ + +The ``api`` feature makes the legacy-compatible ``window.taler`` object +available after asynchronous injection. The extension does not overwrite a +value owned by the page. There are currently no supported callable methods +on this object. Implementation-specific properties are outside the website +contract and must be ignored. In particular, the object exposes no wallet +RPC, balance, transaction, identity, or storage capability. + +``window.talerCallback`` is supplied by the website and is separate from the +injected object. It is the supported way to learn that requested integration +became available; it is not a wallet-provided API method. + +Security and privacy +==================== + +The content script only reads relevant head metadata and user activations; it +cannot access wallet-core or wallet data. Requests cross the extension +runtime channel, and the background rechecks both the sender and the current +preference before acting. Every URI candidate is parsed authoritatively +before it is stored or opened. + +The compatibility entry point must be page-accessible and therefore treats +all URL input as untrusted. It rejects framing and does not connect to the +wallet host or render wallet controls inside a frame. On Chromium, a site +that already knows the stable extension identifier may still be able to probe +that resource. Disabling callback and API integration prevents the standard +presence signals but cannot make the installation undetectable by every +browser-specific probing technique. + +Implementation history and rejected alternatives remain recorded in +:doc:`../design-documents/039-taler-browser-integration`. diff --git a/wallet/index.rst b/wallet/index.rst @@ -0,0 +1,19 @@ +.. + This file is part of GNU TALER. + Copyright (C) 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 + Foundation; either version 3.0, or (at your option) any later version. + +Wallet Manuals +############## + +These manuals describe public integration points offered by GNU Taler wallets. +The generated :doc:`wallet-core` reference documents the programmatic wallet +API. + +.. toctree:: + :maxdepth: 1 + + browser-integration