taler-docs

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

commit 067dc16866716539c4fd03284de9b64b190b7255
parent eda86e5f4883513a3586cc35ee355968d18c335a
Author: Christian Grothoff <christian@grothoff.org>
Date:   Tue,  4 Aug 2026 22:22:32 +0200

introduce SessionID separate from Slug

Diffstat:
Mcore/api-common.rst | 15+++++++--------
Mcore/api-merchant.rst | 36+++++++++++++++++++++++++++++++++++-
Mcore/corebank/post-accounts.rst | 2+-
Mcore/merchant/post-orders-ORDER_ID-paid.rst | 6++++--
Mcore/merchant/post-orders-ORDER_ID-pay.rst | 6++++--
Mcore/merchant/post-private-orders-ORDER_ID-collect.rst | 2+-
Mcore/merchant/post-private-orders.rst | 5+++--
7 files changed, 55 insertions(+), 17 deletions(-)

diff --git a/core/api-common.rst b/core/api-common.rst @@ -292,8 +292,8 @@ without any escaping. We call such an identifier a *slug*. // Non-empty string that can be used as-is as a single path // component of a URL. A slug must only use ASCII alphanumeric - // characters ("A-Z", "a-z", "0-9") and the six punctuation - // characters "-", ".", "_", ":", "=" and "~". Consequently a slug + // characters ("A-Z", "a-z", "0-9") and the five punctuation + // characters "-", ".", "_", ":" and "~". Consequently a slug // never contains a "/" and never requires percent-encoding. // The strings "." and ".." are not valid slugs, as they have a // special meaning in URL paths. @@ -302,12 +302,11 @@ without any escaping. We call such an identifier a *slug*. // documented with the respective endpoint or field. type Slug = string; -A slug is thus the set of RFC 3986 *unreserved* characters, plus ``:`` and -``=``. The character set is deliberately narrower than what RFC 3986 permits -in a path segment: it excludes ``@`` and all sub-delimiters except ``=``, -which are legal in a URL path but cause trouble once a slug is embedded in -other syntax, such as a shell command, a query string or a filename. ``=`` is -permitted because base64-encoded identifiers may end in padding. +A slug is thus the set of RFC 3986 *unreserved* characters, plus ``:``. The +character set is deliberately narrower than what RFC 3986 permits in a path +segment: it excludes ``@`` and all sub-delimiters, which are legal in a URL +path but cause trouble once a slug is embedded in other syntax, such as a +shell command, a query string or a filename. Note that a slug is *not* the same as an opaque identifier that merely happens to be a string: identifiers that may contain arbitrary characters (and thus diff --git a/core/api-merchant.rst b/core/api-merchant.rst @@ -151,6 +151,39 @@ Examples: Unavailabe endpoints (will return 404): https://merchant-backend.example.com/instances/myinst/private/instances +.. _merchant-session-id: + +----------- +Session IDs +----------- + +Payments can be bound to a *session*, which is identified by a session ID. +Session IDs are chosen by the merchant's frontend (or by the client device, +as is the case for the Paivana IDs given to +:http:post:`[/instances/$INSTANCE]/templates/$TEMPLATE_ID`); the backend +merely stores them and uses them to match a payment against the session it +was made for. + +.. ts:def:: SessionID + + // Identifier of the session a payment is bound to. Like a `Slug`, + // a session ID must only use ASCII alphanumeric characters + // ("A-Z", "a-z", "0-9") and the punctuation characters "-", ".", + // "_", ":" and "~", and must not be "." or "..". Unlike a slug, a + // session ID may also contain "=" and may be empty. + // Session IDs are case-sensitive. + type SessionID = string; + +A session ID is thus *not* a slug. It additionally permits ``=`` because +session IDs are frequently base64-encoded identifiers, which may end in +padding. And it may be empty: the empty session ID means that a payment is +not bound to any session. Clients must expect to encounter it, as the +backend itself puts an empty session ID into the ``taler://pay/`` URI of an +order that has no session (the session is the last path component of that +URI and thus cannot simply be omitted), and wallets send back what they were +given. Endpoints for which only an actual session makes sense say so +explicitly and reject the empty session ID. + ----------------- Generic Responses ----------------- @@ -1117,7 +1150,8 @@ open or deferred. // template, the total of the selected products for an // "inventory-cart" template, and the amount of an editable choice // for a "paivana" template. Requires "currency" to be given and - // to match, and must not exceed "max_amount". + // to match, must be in the same currency as "max_amount", and + // must not exceed it. // Since protocol **v34**. min_amount?: Amount; diff --git a/core/corebank/post-accounts.rst b/core/corebank/post-accounts.rst @@ -13,7 +13,7 @@ // Must be at most 126 characters long. Implementations // may further restrict the character set; libeufin-bank // accepts only the RFC 3986 unreserved characters (that - // is, a slug without ":" and "="). + // is, a slug without ":"). username: Slug; // Password of the account used for authentication diff --git a/core/merchant/post-orders-ORDER_ID-paid.rst b/core/merchant/post-orders-ORDER_ID-paid.rst @@ -68,6 +68,8 @@ // database access). h_contract: HashCode; - // Session id for which the payment is proven. - session_id: Slug; + // Session ID for which the payment is proven. Must not be + // empty: proving a payment only makes sense for an actual + // session. + session_id: SessionID; } diff --git a/core/merchant/post-orders-ORDER_ID-pay.rst b/core/merchant/post-orders-ORDER_ID-pay.rst @@ -252,8 +252,10 @@ wallet_data?: PayWalletData; // The session for which the payment is made (or replayed). - // Only set for session-based payments. - session_id?: Slug; + // Only set for session-based payments. The empty session ID + // is treated like the field being absent (wallets do send it + // that way). + session_id?: SessionID; } diff --git a/core/merchant/post-private-orders-ORDER_ID-collect.rst b/core/merchant/post-private-orders-ORDER_ID-collect.rst @@ -78,7 +78,7 @@ // Session ID to store with the payment, like the ``session_id`` of // a wallet payment. Allows a point-of-sale device to tag and later // list the orders it collected. Absent for no session. - session_id?: Slug; + session_id?: SessionID; // For v1 contracts, the index of the choice to complete within // the ``choices`` array of the contract terms. Mandatory for v1 diff --git a/core/merchant/post-private-orders.rst b/core/merchant/post-private-orders.rst @@ -116,9 +116,10 @@ payment_target?: string; // The session for which the payment is made (or replayed). - // Only set for session-based payments. + // Only set for session-based payments. The empty session ID + // is treated like the field being absent. // Since protocol **v6**. - session_id?: Slug; + session_id?: SessionID; // Specifies that some products are to be included in the // order from the inventory. For these inventory management