taler-docs

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

commit 77e72cd258a642c08648c8e666cc7c918abccc6a
parent 45def97aa7b1113b423f56eea4692b4750e1e901
Author: Christian Grothoff <christian@grothoff.org>
Date:   Thu,  6 Aug 2026 15:43:34 +0200

expand auditor spec

Diffstat:
Mcore/api-auditor.rst | 72+++++++++++++++++++++++++++++++++++++++++++-----------------------------
Mcore/auditor/get-monitoring-aml-holds.rst | 20++++++++++++--------
2 files changed, 55 insertions(+), 37 deletions(-)

diff --git a/core/api-auditor.rst b/core/api-auditor.rst @@ -486,29 +486,36 @@ paid; a ``wire_out`` row is. This endpoint lists the transfers that are stuck in between, one row per wire transfer identifier, and the row disappears once the transfer is made. -The exchange has one legitimate reason to sit on such funds: it may not pay -out to an account whose KYC/AML requirements are still open. ``aml_hold`` -says whether the auditor found such a requirement. The two cases are also -totalled separately, as the ``total_aml_hold`` and ``total_transfer_lag`` -balances (see :ref:`balances-list`), so that "the exchange is waiting for -legitimization data" and "the exchange is not paying" cannot be confused with -each other or with having paid. +The exchange has two legitimate reasons to sit on such funds. It may not pay +out to an account whose KYC/AML requirements are still open; and it need not +make a transfer whose amount would not survive the wire fee, in which case it +waits for further deposits to the same account. ``deferral_reason`` says which +of the two the exchange gave, or ``NONE`` if it gave neither. The three cases +are also totalled separately, as the ``total_aml_hold``, +``total_small_aggregate`` and ``total_transfer_lag`` balances (see +:ref:`balances-list`), so that "the exchange is waiting for legitimization +data", "the exchange is waiting for more deposits" and "the exchange is not +paying" cannot be confused with each other or with having paid. Whether a hold is *justified* is a question for a human, not for the auditor: the auditor reports what is being withheld and from whom, and leaves the judgement to the reader. What it does check is that the exchange does not get -to withhold money silently. +to withhold money silently, and that the reason it gives is consistent with +everything else the auditor can see. .. note:: - ``aml_hold`` is the auditor's own inference, drawn from the KYC measures on - file for the recipient, not a claim replicated from the exchange. The - exchange records its reason in ``aggregation_transient``, a table that has no - serial ID and is updated in place, so ``taler-auditor-sync`` cannot replicate - it and an external auditor never sees it. An exchange-internal audit (the - ``-i`` option of **taler-helper-auditor-transfer**) does read that table, and - reports any disagreement between it and the inference as a row inconsistency - rather than silently deferring to the exchange. + ``deferral_reason`` is the exchange's own statement, taken from its + append-only ``aggregation_deferrals`` table, which is replicated to the + auditor. The auditor does not overrule it, but it does check it: the amount + against its own recomputation of what the aggregate is worth, and a ``KYC`` + claim against the ``legitimization_measures`` and + ``legitimization_processes`` tables. If the exchange names a measure that is + not open, the hold is still reported as a ``KYC`` hold and a row + inconsistency against ``aggregation_deferrals`` is raised alongside it. An + exchange-internal audit (the ``-i`` option of + **taler-helper-auditor-transfer**) additionally compares the claim with the + live ``aggregation_transient`` table, which cannot be replicated. .. include:: auditor/get-monitoring-aml-holds.rst @@ -605,23 +612,30 @@ Balances Returns the various balances the auditor tracks for the exchange, such as coins in circulation, fees earned, losses experienced, etc. -Two of the keys concern money the exchange owes a merchant and has not sent: +Three of the keys concern money the exchange owes a merchant and has not sent. +Which one an amount lands in follows the reason the exchange gave for not +sending it: ``total_aml_hold`` - The exchange decided what it owes on a wire transfer, did not execute it, and - has a KYC measure open against the recipient that explains the delay. This - is money withheld pending legitimization. + The exchange says a KYC/AML requirement against the recipient is still open. + This is money withheld pending legitimization. + +``total_small_aggregate`` + The exchange says what it has collected for the account so far would not + cover the wire fee, so it is waiting for further deposits. This is normal + operation rather than an irregularity; it has a key of its own so that it + does not inflate the other two, which are not. ``total_transfer_lag`` - The same, except that the auditor found no legitimization requirement for the - recipient. This is money the exchange simply has not paid out. - -Both are current state rather than a running tally: the amount is recomputed -from the outstanding transfers on every audit run, so it falls again as -transfers are executed, and a transfer moves between the two keys if the KYC -measure that explained it is decided (or if one appears). They are distinct -from ``total_amount_lag``, which counts deposits the exchange has not -aggregated at all. The individual transfers behind both keys are listed by + The exchange gave no reason at all. This is money the exchange simply has + not paid out. + +All three are current state rather than a running tally: the amount is +recomputed from the outstanding transfers on every audit run, so it falls again +as transfers are executed, and a transfer moves between the keys if the +exchange changes what it says about it. They are distinct from +``total_amount_lag``, which counts deposits the exchange has not aggregated at +all. The individual transfers behind all three keys are listed by :ref:`aml-holds-list`. .. include:: auditor/get-monitoring-balances.rst diff --git a/core/auditor/get-monitoring-aml-holds.rst b/core/auditor/get-monitoring-aml-holds.rst @@ -54,14 +54,18 @@ // fees. The wire fee is not yet deducted. amount : Amount; - // True if the exchange has a KYC measure open against the - // recipient, so that withholding the funds is explained. - // False if the auditor found no legitimization requirement, - // in which case the exchange is simply not paying. - aml_hold : boolean; - - // The open measure the hold was attributed to, or 0 if - // aml_hold is false. + // Reason the exchange gave for not making the transfer: + // "KYC" if a legitimization requirement against the recipient + // is still open, "AMOUNT_TOO_SMALL" if the aggregate would not + // cover the wire fee and the exchange is waiting for further + // deposits, "NONE" if the exchange gave no reason at all. + deferral_reason : "KYC" | "AMOUNT_TOO_SMALL" | "NONE"; + + // The measure the exchange named as blocking the payout, or 0 + // if it named none. Note that the auditor checks whether that + // measure is in fact open and raises a row inconsistency if it + // is not, but still reports the hold as the exchange classified + // it. legitimization_measure_serial_id : Integer; // When the auditor first saw this transfer being withheld.