Architecture#
camt053 is one facade, camt053.services, with four surfaces in front of it
and five packages of logic behind it. Every interface (the Python API, the
Click CLI, the FastAPI REST API, and the companion MCP and LSP servers) calls
the facade, so they behave the same.
Click CLI FastAPI REST API camt053-mcp camt053-lsp
\ | | /
+--------------+-------+---------+-------------+
|
camt053.services
|
+------------+----------+-----------+----------------+
| | | |
parse/ reversal/ xml/ validation/
statement reversal builder template + the IBAN, BIC, LEI,
parser, official ISO XSD JSON Schema
reason codes
Module |
Responsibility |
|---|---|
|
Namespace-agnostic statement parser, return-reason helpers, de-duplication keys, lenient parse reports |
|
Builds flat reversing-entry records from parsed entries, with deterministic references |
|
Renders the camt.053 and pacs.004 templates, re-serialises statements, validates against the ISO XSDs |
|
IBAN, BIC, LEI, ISO 4217 currency and JSON-Schema validators |
|
Per-revision rules ( |
|
CBPR+ November 2026 readiness checks and SWIFT X charset cleansing |
|
XXE-safe parsing guard and path-traversal-checked output |
|
The shared facade backing every interface |
|
The suite’s membership and versioning policy |
The flow of one reversal#
services.generate_reversal(xml, reason_code="AC04")parses the statement withdefusedxmlinto aParsedDocument. The REST API first passes every payload throughservices.guard_xml(security.xml_guard: byte cap, no inline DOCTYPE or ENTITY); library callers handling untrusted input call it themselves.The entries carrying the reason code are selected, and
reversal.build_reversal_recordturns each into a flat record: the credit/debit indicator flipped,RvslIndset, the reason carried inRtrInf, and a reference derived from the original bystable_reversal_reference, so a retry produces the same reference.xml.generate_xmlrenders thecamt.053.001.14Jinja template and validates the result against the bundled XSD before returning it. A document that does not validate is never returned.
Where the complexity is#
complexity-baseline.json lists the functions and files over the per-function
ceilings. It may only shrink: scripts/check_complexity.py fails when an
entry gets worse and when one improves without the baseline being updated.