taler-docs

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

commit 005d1960b981176633f6519e40b8af67cbbd3964
parent 94229c03d8e56dc54cceb24893e0a4a96486810d
Author: Antoine A <>
Date:   Fri, 18 Sep 2026 17:16:10 +0200

DD104

Diffstat:
Ddesign-documents/104-status.rst | 232-------------------------------------------------------------------------------
Adesign-documents/104-wire-gateway-management-API.rst | 239+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Mdesign-documents/index.rst | 1+
3 files changed, 240 insertions(+), 232 deletions(-)

diff --git a/design-documents/104-status.rst b/design-documents/104-status.rst @@ -1,231 +0,0 @@ -DD 104: Wire Gateway Observability and Administration -##################################################### - -:Design status: Draft -:Implementation status: Not started -:DD shepherd: Antoine d'Aligny -:Historical contributors: Antoine d'Aligny -:First published: 2026-09-18 -:Last substantive change: 2026-09-18 - -Summary -======= - -This design document presents the challenges we currently face when handling -transaction failures in wire gateway adapters and proposes a solution for -addressing them. - -Motivation -========== - -In the current design and implementations, both incoming and outgoing -transactions can fail without administrators being notified or having the -ability to take corrective action. - -Requirements -============ - -* The solution must allow administrators to see failures, understand their - causes, and possibly fix them. -* The solution must be lightweight to implement in wire gateway adapters, as - the goal of this API is to provide a thin wrapper around how each - implementation works. Common logic that can be extracted into another - component should be. - -Proposed Solution -================= - -Terminology ------------ - -* `in_tx`: final incoming transaction -* `out_tx`: final outgoing transaction -* `talerable_in_tx`: talerable final incoming transaction (RESERVE | KYC | MAP) -* `talerable_out_tx`: talerable final outgoing transaction (deposit) -* `transfer`: initiated talerable outgoing transaction -* `initiated`: initiated outgoing transaction -* `bounce`: bounced invalid outgoing transaction - -Current API State ------------------ - -We already have endpoints for querying Talerable transactions: -`talerable_in_tx` with `GET /history/incoming` and `talerable_out_tx` with -`GET /history/outgoing`. - -We also already have endpoints for querying `transfer` with `GET /transfers` -and `GET /transfers/$ROW_ID`. - -What is missing is access to raw (incompled, malformed, etc) transactions, `in_tx` and `out_tx`, as well -as initiated and bounced transactions, `initiated` and `bounce`. - -Generic API Design ------------------- - -Each adapter works differently. In most adapters, `transfer` and `bounce` -produce an `initiated` operation, while other payment systems, such as -Cyclos, provide a proper way to perform a bounce idempotently and have a -specific bounce operation. - -Each adapter also has different internal unique identifiers. For example, -`libeufin_nexus` uses three of them while `depolymerizer-bitcoin` has a -single transaction ID. - -We need an API that can expose enough detail for manual reconciliation while -remaining generic enough to reuse the same logic across all adapters. - -For `transfer`, we already have the paginated `GET /transfers` endpoint and -the single-entry `GET /transfers/$ROW_ID` endpoint. The problem with this -design is that it is not well suited to following the progress of transfers. -Transfers do not progress or reach finality in the order in which they are -created. - -I propose adding a new status-history endpoint, -`GET /transfers/status-history`. This will allow administrators to understand -the lifecycle of a transaction and track the progress of all transfers in -real time. - -We also need new endpoints for `incoming` and `outgoing` transactions, -including paginated and single-entry endpoints, so that administrators can -inspect all transactions, including incomplete or invalid ones. This is -necessary to understand and debug why an incoming transaction never reaches -the Talerable history. - -Finally, we need a way to track both `initiated` and `bounce` transactions -using new endpoints providing paginated listings, status histories and -single-entry views. - -We could potentially remove all `transfer` endpoints, since transfers are a -subset of `initiated` operatuibs. Whether to do so depends on whether the -transfer-specific API remains useful as a higher-level abstraction. - -We could also enforce a single `initiated` operation concept, event if underneath -bounces works differently. As long as doing this it not too messy for the -database layer we should pursue this simplification. - -.. ts:def:: InTx - - interface InTx { - // Opaque identifier of the returned record. - row_id: SafeUint64; - - // Unstructured implementation specific fields that must be shown. - // Contains at least the unique identifiers to be used for manual reconciliation. - details: {string: string}; - - // Date of the transaction. - date: Timestamp; - - // Amount received before credit_fee. - amount?: Amount; - - // Unstructured transaction subject - subject?: string; - - // Fee paid by the creditor. - // If not null, creditor actually received amount - credit_fee - credit_fee?: Amount; - - // Full payto URI to identify the sender of funds. - debit_account?: string; - - // ID of the bounce operation if bounced - bounce_id?: SafeUint64; - } - -.. ts:def:: OutTx - - interface OutTx { - // Opaque identifier of the returned record. - row_id: SafeUint64; - - // Unstructured implementation specific fields that must be shown. - // Contains at least the unique identifiers to be used for manual reconciliation. - details: {string: string}; - - // Date of the transaction. - date: Timestamp; - - // Amount received before credit_fee. - amount?: Amount; - - // Unstructured transaction subject - subject?: string; - - // Fee paid by the debtor. - // If not null, debtor actually paid amount + debit_fee - debit_fee?: Amount; - - // Full payto URI to identify the receiver of funds. - credit_account?: string; - } - -.. ts:def:: InitiatedTx - - interface InitiatedTx { - // Opaque ID of this operation. - operation_id: SafeUint64; - - // Amount to transfer. - amount: Amount; - - // The recipient's account identifier as a full payto:// URI. - credit_account: string; - - // Optional ID of the wire transfer initiation if operation is a transfer - transfer_id?: SafeUint64; - - // Optional ID of the bounced incoming transaction if operation is a bounce - bounced_id?: SafeUint64; - - // Current status - // pending: in progress - // transient_failure: has failed but may succeed later - // permanent_failure: has failed permanently and will never reach finality - // success: has succeeded and reached finality - // late_failure: has failed permanently after reaching the success status - status: "pending" | "transient_failure" | "permanent_failure" | "success" | "late_failure"; - - // Timestamp that indicates when this status was reached. - timestamp: Timestamp; - } - -.. ts:def:: InitiatedStatus - - interface InitiatedStatus { - // Opaque ID of this operation. - operation_id: SafeUint64; - - // Opaque ID of this status, used for pagination. - row_id: SafeUint64; - - // pending: in progress - // transient_failure: has failed but may succeed later - // permanent_failure: has failed permanently and will never reach finality - // success: has succeeded and reached finality - // late_failure: has failed permanently after reaching the success status - status: "pending" | "transient_failure" | "permanent_failure" | "success" | "late_failure"; - - // Optional unstructured messages about the status. Can be used to document the reasons for failure or the state of progress. - status_msg?: string; - - // Timestamp that indicates when this status was reached. - timestamp: Timestamp; - } - -Test Plan -========= - - - -Definition of Done -================== - -Alternatives -============ - -Drawbacks -========= - -Discussion / Q&A -================ -\ No newline at end of file diff --git a/design-documents/104-wire-gateway-management-API.rst b/design-documents/104-wire-gateway-management-API.rst @@ -0,0 +1,238 @@ +DD 104: Wire Gateway Management API +################################### + +:Design status: Draft +:Implementation status: Not started +:DD shepherd: Antoine d'Aligny +:Historical contributors: Antoine d'Aligny +:First published: 2026-09-18 +:Last substantive change: 2026-09-18 + +Summary +======= + +This design document presents the challenges we currently face when handling +transaction failures in wire gateway adapters and proposes a solution for +addressing them. + +Motivation +========== + +In the current design and implementations, both incoming and outgoing +transactions can fail without administrators being notified or having the +ability to take corrective action. + +Requirements +============ + +* The solution must allow administrators to see failures, understand their + causes, and possibly fix them. +* The solution must be lightweight to implement in wire gateway adapters, as + the goal of this API is to provide a thin wrapper around how each + implementation works. Common logic that can be extracted into another + component should be. + +Proposed Solution +================= + +Terminology +----------- + +* `in_tx`: final incoming transaction +* `out_tx`: final outgoing transaction +* `talerable_in_tx`: talerable final incoming transaction (RESERVE | KYC | MAP) +* `talerable_out_tx`: talerable final outgoing transaction (deposit) +* `transfer`: initiated talerable outgoing transaction +* `initiated`: initiated outgoing transaction +* `bounce`: bounced invalid outgoing transaction + +Current API State +----------------- + +We already have endpoints for querying Talerable transactions: +`talerable_in_tx` with `GET /history/incoming` and `talerable_out_tx` with +`GET /history/outgoing`. + +We also already have endpoints for querying `transfer` with `GET /transfers` +and `GET /transfers/$ROW_ID`. + +What is missing is access to raw (incompled, malformed, etc) transactions, `in_tx` and `out_tx`, as well +as initiated and bounced transactions, `initiated` and `bounce`. + +Generic API Design +------------------ + +Each adapter works differently. In most adapters, `transfer` and `bounce` +produce an `initiated` operation, while other payment systems, such as +Cyclos, provide a proper way to perform a bounce idempotently and have a +specific bounce operation. + +Each adapter also has different internal unique identifiers. For example, +`libeufin_nexus` uses three of them while `depolymerizer-bitcoin` has a +single transaction ID. + +We need an API that can expose enough detail for manual reconciliation while +remaining generic enough to reuse the same logic across all adapters. + +For `transfer`, we already have the paginated `GET /transfers` endpoint and +the single-entry `GET /transfers/$ROW_ID` endpoint. The problem with this +design is that it is not well suited to following the progress of transfers. +Transfers do not progress or reach finality in the order in which they are +created. + +I propose adding a new status-history endpoint, +`GET /transfers/status-history`. This will allow administrators to understand +the lifecycle of a transaction and track the progress of all transfers in +real time. + +We also need new endpoints for `incoming` and `outgoing` transactions, +including paginated and single-entry endpoints, so that administrators can +inspect all transactions, including incomplete or invalid ones. This is +necessary to understand and debug why an incoming transaction never reaches +the Talerable history. + +Finally, we need a way to track both `initiated` and `bounce` transactions +using new endpoints providing paginated listings, status histories and +single-entry views. + +We could potentially remove all `transfer` endpoints, since transfers are a +subset of `initiated` operatuibs. Whether to do so depends on whether the +transfer-specific API remains useful as a higher-level abstraction. + +We could also enforce a single `initiated` operation concept, event if underneath +bounces works differently. As long as doing this it not too messy for the +database layer we should pursue this simplification. + +.. ts:def:: InTx + + interface InTx { + // Opaque identifier of the returned record. + row_id: SafeUint64; + + // Unstructured implementation specific fields that must be shown. + // Contains at least the unique identifiers to be used for manual reconciliation. + details: {string: string}; + + // Date of the transaction. + date: Timestamp; + + // Amount received before credit_fee. + amount?: Amount; + + // Unstructured transaction subject + subject?: string; + + // Fee paid by the creditor. + // If not null, creditor actually received amount - credit_fee + credit_fee?: Amount; + + // Full payto URI to identify the sender of funds. + debit_account?: string; + + // ID of the bounce operation if bounced + bounce_id?: SafeUint64; + } + +.. ts:def:: OutTx + + interface OutTx { + // Opaque identifier of the returned record. + row_id: SafeUint64; + + // Unstructured implementation specific fields that must be shown. + // Contains at least the unique identifiers to be used for manual reconciliation. + details: {string: string}; + + // Date of the transaction. + date: Timestamp; + + // Amount received before credit_fee. + amount?: Amount; + + // Unstructured transaction subject + subject?: string; + + // Fee paid by the debtor. + // If not null, debtor actually paid amount + debit_fee + debit_fee?: Amount; + + // Full payto URI to identify the receiver of funds. + credit_account?: string; + } + +.. ts:def:: InitiatedTx + + interface InitiatedTx { + // Opaque ID of this operation. + operation_id: SafeUint64; + + // Amount to transfer. + amount: Amount; + + // The recipient's account identifier as a full payto:// URI. + credit_account: string; + + // Optional ID of the wire transfer initiation if operation is a transfer + transfer_id?: SafeUint64; + + // Optional ID of the bounced incoming transaction if operation is a bounce + bounced_id?: SafeUint64; + + // Current status + // pending: in progress + // transient_failure: has failed but may succeed later + // permanent_failure: has failed permanently and will never reach finality + // success: has succeeded and reached finality + // late_failure: has failed permanently after reaching the success status + status: "pending" | "transient_failure" | "permanent_failure" | "success" | "late_failure"; + + // Timestamp that indicates when this status was reached. + timestamp: Timestamp; + } + +.. ts:def:: InitiatedStatus + + interface InitiatedStatus { + // Opaque ID of this operation. + operation_id: SafeUint64; + + // Opaque ID of this status, used for pagination. + row_id: SafeUint64; + + // pending: in progress + // transient_failure: has failed but may succeed later + // permanent_failure: has failed permanently and will never reach finality + // success: has succeeded and reached finality + // late_failure: has failed permanently after reaching the success status + status: "pending" | "transient_failure" | "permanent_failure" | "success" | "late_failure"; + + // Optional unstructured messages about the status. Can be used to document the reasons for failure or the state of progress. + status_msg?: string; + + // Timestamp that indicates when this status was reached. + timestamp: Timestamp; + } + +Management logic +---------------- + +On top of this API, we could build a Management SPA to support administrative operations. +The UI would show recent failures and track whether someone has reviewed them and made a decision on how to handle them. +We could also extend the API with administrative operations, such as manually requesting a retry. + +Test Plan +========= + + + +Definition of Done +================== + +Alternatives +============ + +Drawbacks +========= + +Discussion / Q&A +================ +\ No newline at end of file diff --git a/design-documents/index.rst b/design-documents/index.rst @@ -117,4 +117,5 @@ documents. The lifecycle metadata in each document is authoritative. See 101-semantic-token-families 102-systemd-service-restart-policy 103-https-wallet-links + 104-wire-gateway-management-API 999-template