Pre-submission safety gate for ISO 20022 payment messages. Catches the gap between schema-valid and network-acceptable before you submit.
Project description
tollgate
Catches ISO 20022 payment messages that pass schema validation and still get rejected by the network — before you find out the hard way.
A pacs.008 payment message can be 100% valid XML, pass every XSD check, and still bounce off a real clearing network — because some of the rules that matter live outside the schema entirely. Tollgate catches that gap.
Quickstart
pip install iso-tollgate
tollgate validate payment.xml
1 error(s), 0 warning(s) found in payment.xml:
ERROR charset_violation -- FIToFICstmrCdtTrf/CdtTrfTxInf/Dbtr/Nm
Contains character(s) outside SWIFT's character set X: 'ü'. This is
schema-valid XML (ISO 20022 permits full Unicode) but SWIFT's network
layer restricts allowed characters independently of the schema --
this will not be caught by XSD validation alone.
That's a real example, not a mockup — every command in this README was actually run before being written down. No payment file handy? Generate one:
tollgate generate --count 1 --rule-id charset_violation --output-dir /tmp/fixtures
tollgate validate /tmp/fixtures/charset_violation_0.xml
→ Full usage guide — every command, every flag, the Python library API, batch directory checking, the GitHub Action → Why this exists — the dated deadline behind it, the AI design philosophy, what was found and fixed during development → Sources — every rule traced to a citation
What it checks
One message type in v1: pacs.008.001.08, the FI-to-FI customer credit transfer used across Fedwire, CHIPS, and SWIFT CBPR+.
| Check | Catches |
|---|---|
| Schema validity | Standard XSD structural validation. The floor everything else stands on. |
| SWIFT character set | A character outside SWIFT's allowed set — schema-valid, network-invalid. |
| Address structure | Free-format addresses used where structure is required, or line counts the schema allows but a network's guidelines don't. |
| Truncation signals | A value landing at exactly 35 or 70 characters — old legacy line limits — in a field with a much higher modern limit. Reported as a warning, not a certainty. |
| Network-mandatory gaps | Fields the schema marks optional that a real network requires in practice (e.g. UETR for Fedwire). |
| Currency decimal precision | An amount's decimal places don't match its currency's defined exponent (e.g. JPY, which has zero decimal places, formatted with two). Reported as a warning — the failure mode is silent misinterpretation, not certain rejection. |
Every rule traces to a primary source — see docs/SOURCES.md. No rule ships without one.
Not a compliance tool
Tollgate is a developer-facing sanity check, not a replacement for SWIFT certification or MyStandards testing. It covers one message type, checks structure and format (not business logic like BIC reachability), and is explicit in docs/why.md about every limitation found during development. If it can't catch something, the docs say so.
Three ways to use it
| CLI | tollgate validate payment.xml · tollgate validate-dir payments/ |
| Python library | from tollgate import check_message, check_file, check_directory |
| CI | uses: iso-tollgate/tollgate/.github/actions/validate@main |
Details and examples for all three: docs/usage.md.
Status
168 tests passing, 3 skip cleanly without an ANTHROPIC_API_KEY set (these 3 exercise --explain against the real Anthropic API and were live-verified once, 2026-06-21, on a real machine with a real key — see CLAUDE.md for the re-verification rule if explainer.py or prompts.py change). The full deterministic suite — every validation rule, the generator, the eval harness, both APIs — needs zero API key to verify.
--explain has been live-tested against the real model: it correctly names the violated field and cause, and correctly hedges on warning-severity (heuristic) findings rather than asserting them as certain failures — verified, not assumed.
Published on PyPI: pip install iso-tollgate. A Homebrew tap exists at homebrew-tollgate — CI verifies the formula's syntax and style on every change, but a full brew install hasn't been confirmed end-to-end yet, so pip install is the recommended path for now.
License
Apache 2.0. See LICENSE.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file iso_tollgate-0.1.1.tar.gz.
File metadata
- Download URL: iso_tollgate-0.1.1.tar.gz
- Upload date:
- Size: 312.6 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.14.6
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
7734ffab03e749eb2b3c2a2f37081ff1ca405aa3ac1c41b6735e36d4b3e17fb1
|
|
| MD5 |
3dc7a8987f5ef39f98c98caff79991d6
|
|
| BLAKE2b-256 |
f568b9f488d2e310eae49b375cfdee295b6bd7c43fd66c3fcd1464613fa673ad
|
File details
Details for the file iso_tollgate-0.1.1-py3-none-any.whl.
File metadata
- Download URL: iso_tollgate-0.1.1-py3-none-any.whl
- Upload date:
- Size: 55.7 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.14.6
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
11d75abe5bfaed80357f3e69940d3da27151a8111638103cb4f36972c71cfcf8
|
|
| MD5 |
a74d74b59aa1a3f37d362b8e378811fa
|
|
| BLAKE2b-256 |
6de85578542ad264cdc90b12b0c2abd007f7093b07c0ccfd82ab6dd20fce1a69
|