commit 83d19c91d889d7d7234b83ac19a8c29563059b5d
parent e4687d3857c036c6c88e1cf0ad3372eefed4bd2c
Author: Christian Grothoff <christian@grothoff.org>
Date: Wed, 5 Aug 2026 21:30:24 +0200
expand auditor specs to match latest code
Diffstat:
1 file changed, 67 insertions(+), 0 deletions(-)
diff --git a/core/api-auditor.rst b/core/api-auditor.rst
@@ -470,6 +470,54 @@ transfers).
.. include:: auditor/patch-monitoring-wire-format-inconsistency-SERIAL_ID.rst
+.. _aml-holds-list:
+
+AML Holds
+---------
+
+This endpoint is used to obtain a list of the wire transfers the exchange
+aggregated but did not execute.
+
+The exchange aggregates the deposits it owes to a merchant, decides what the
+payout should be, records that decision, and only then makes the wire
+transfer. Between those two steps the money is still the exchange's. An
+``aggregation_tracking`` row is therefore not proof that the merchant was
+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.
+
+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.
+
+.. 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.
+
+.. include:: auditor/get-monitoring-aml-holds.rst
+
+
+.. include:: auditor/patch-monitoring-aml-holds-SERIAL_ID.rst
+
+
+
+
.. _closure-lags-list:
Closure Lags
@@ -557,6 +605,25 @@ 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:
+
+``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.
+
+``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
+:ref:`aml-holds-list`.
+
.. include:: auditor/get-monitoring-balances.rst