Changelog¶
All notable changes to this project will be documented in this file.
The format is based on Keep a Changelog,
and this project adheres to Semantic Versioning.
This package’s version follows the pain001
suite; the 0.0.1 release targets the 0.0.53 line of pain001.
[Unreleased]¶
Nothing yet.
[0.0.74] - 2026-10-21¶
Released in lockstep with pain001 0.0.74, the family’s convergence
release (this package skips 0.0.73, which pain001-mcp published
alone). Two parser fixes change what parse_mt101 accepts; everything
else is supply chain, CI and documentation.
Security¶
An unterminated block-4 opener no longer costs quadratic time (CWE-1333).
parse_mt101found the{4:...-}envelope with a lazy regular expression, so each{4:without a closing-}made the search scan to the end of the text again: 120 KB of{4:took about 110 seconds before the input was rejected. The envelope is now found in one pass, with the same result on every input. Every release up to 0.0.72 is affected.
Fixed¶
:30:dates that do not exist are rejected with aValueErrornaming:30:.000000used to come back as2000-00-00and260230as2026-02-30.:32B:amounts outside the SWIFT form are rejected with aValueErrornaming:32B:. Behaviour change: an amount with a dot (EUR1.234,EUR1000.50) used to be read as a decimal point and is now refused, because SWIFT amounts never carry one;1,2,3and a bare,now raise the documented error instead of float’s own; an amount over 15 characters (SWIFT15d), which could become an infinite amount, is refused.scripts/check_suite_consistency.pycompares the tree with this package’s own release on PyPI instead of the core’s.examples/01_minimal_parse.pyno longer prints names, IBANs and BICs (CodeQLpy/clear-text-logging-sensitive-data); it lists the party keys with their values redacted.CITATION.cffstates the licence as CFF 1.2.0 requires (Apache-2.0andMIT, either at the user’s option); the SPDX expression it held did not validate.
Changed¶
pain001 >= 0.0.74, < 1, inpyproject.tomland everyrequirements/*.in.Every CI install is hash-pinned from
requirements/*.txt(OpenSSF Scorecard Pinned-Dependencies), and the release build runs with--no-isolationfrom the pinned build tree.certifiis floored at 2026.10.19 (GHSA-6q48-6c7w-9gw2) in the tooling trees that resolve it.New CI gates:
pip-auditover every requirements file, complexity ceilings againstcomplexity-baseline.json(empty:parse_mt101and_parse_transactionwere split under the 60-line ceiling, with no change in output), Atheris fuzzing (fuzz/) and Hypothesis fuzzing in the test suite, mypy--strictoverscripts/, andscripts/verify_versions.py(“Version sources agree”), which fails when any restatement of the version, or thepain001floor, differs frompyproject.toml.The README follows the family template, with a demo (
.github/demo.gif, rendered bymake demo), and its License section now states the dualApache-2.0 OR MITgrant instead of Apache-2.0 alone. Newdocs/COMPARISON.mdanddocs/POLICIES.md;docs/benchmarks.mdis nowdocs/BENCHMARKS.mdwith a fresh run.Every page of the documentation site links the author from its copyright line.
Since 0.0.72 on
main: the sequence-B override test uses a mod-97 valid IBAN and real BICs, every SPDX header statesApache-2.0 OR MIT,make formatandmake lintrun ruff as CI does, and seven GitHub Actions were updated.
[0.0.72] - 2026-09-28¶
Aligns the pain001 suite on 0.0.72, the core’s coordinated release:
ISO 20022 schemas and Schematron validation rules, SLSA level 3 provenance
attestations, and dependency updates. Nothing in this package changed.
Changed¶
Version aligned to
0.0.72across allpain001packages.The README and the documentation index link What is pain.001?, an explainer of the target message’s structure and versions.
[0.0.71] - 2026-09-26¶
Aligns the pain001 suite on 0.0.71, the core’s coordinated release:
request-local CEL policy rules, review-only correction suggestions,
explicit SFTP upload delivery, and release artifact inspection.
Nothing in this package changed.
Changed¶
Version aligned to
0.0.71across all fivepain001packages.SECURITY.md’s supported-version table follows the bump.
[0.0.70] - 2026-09-13¶
Aligns the pain001 suite on 0.0.70: the core’s rail rules now read the
CSV pipeline’s column names, and its optional dependencies load on use
rather than on import. Nothing in this package changed.
Changed¶
Version aligned to
0.0.70across all fivepain001packages.SECURITY.md’s supported-version table follows the bump.
[0.0.69] - 2026-09-12¶
Aligns the pain001 suite on 0.0.69, the core’s third example-corpus
release: the tier 2 and 3 market packs, the CSV pipeline extension and
the pain.001 twin foundation (lossless ISO JSON twins with their
schemas). Nothing in this package changed.
Changed¶
Version aligned to
0.0.69across all fivepain001packages.SECURITY.md’s supported-version table follows the bump.
[0.0.68] - 2026-09-12¶
Aligns the pain001 suite on 0.0.68, the core’s second example-corpus
release: the tier-1 market packs (UK, SEPA core, US, CH, SE), coverage
files named by recipe and focus, and the tooling to apply a bank’s own
guideline privately. Nothing in this package changed.
Changed¶
Version aligned to
0.0.68across all fivepain001packages.SECURITY.md’s supported-version table follows the bump.
[0.0.67] - 2026-09-12¶
Aligns the pain001 suite on 0.0.67, the core’s first example-corpus
release: validated pain.001 example files per country and rail with
their provenance, and the schema coverage sets. Nothing in this package
changed.
Changed¶
Version aligned to
0.0.67across all fivepain001packages.SECURITY.md’s supported-version table follows the bump.
[0.0.66] - 2026-09-12¶
Aligns the pain001 suite on 0.0.66, the core release that adds
cross-record duplicate detection, the /api/v1/ui dashboard, GPG
flags and OpenTelemetry spans. Nothing in this package changed.
Changed¶
Version aligned to
0.0.66across all fivepain001packages.SECURITY.md’s supported-version table follows the bump.
[0.0.65] - 2026-08-29¶
Aligns the pain001 suite on one version number, and adds the gates this
repository was missing.
Added¶
benches/bench_parse_mt101.py. MT101 genuinely batches — sequence B repeats once per instruction — so unlike the MT103 loader there is a real scaling axis, and it is the one a payroll run moves along. Cost is linear across ten to five thousand instructions (exponent 1.03, roughly 6-8 µs each).The benchmark prints the record count beside the timings. A loader that silently stopped after the first instruction would show a falling µs/txn as the input grew — batching to read, dividing by work never done in fact. The sibling
pain001-loader-mt103behaves exactly that way because an MT103 carries one transfer, and the two are easy to assume alike.docs/benchmarks.md,CONTRIBUTING.md.scripts/check_suite_consistency.pyand a scheduledSuite Consistencyworkflow comparing this tree, and every published member, against PyPI.tests/test_suite_conformance.py, the shared suite conformance gate.
Changed¶
Version aligned to
0.0.65across all fivepain001packages, which had drifted to0.0.62,0.0.64,0.0.63,0.0.62and0.0.63.SECURITY.md’s supported-version table follows the bump.
[0.0.62] - 2026-08-21¶
Added¶
Benchmarks for the block-4 wire format and field-dense transactions. The 0.0.61 set measured one shape: a bare field list with a uniform transaction. Banks send that list wrapped in
{1:...}{2:...}{4: ... -}, which is the only thing that exercises_unwrap_block4— previously unbenchmarked. Measured at 1.10x a bare list._lookupsearches tag by tag, so the risk is it going quadratic in the number of fields present, which uniform fixtures cannot show. A transaction carrying every optional field costs 1.10x a minimal one.ruff format --checkin CI, whichpain001-loader-xlsxalready enforced and this repo did not. Four files had drifted out of format with nothing configured to notice — the same shape of gap as a lockfile nobody installs from.
[0.0.61] - 2026-08-20¶
Suite release with pain001 0.0.61. No change in this package.
The core’s 0.0.61 is a performance release — libxml2 XSD validation and a fix for quadratic CSV diagnostics — and neither touches the MT101 parser, which does its own parsing and does not go through either path. The version moves because every member of the suite ships the same number.
[0.0.60] - 2026-08-20¶
Version-alignment release. No public API change and no change to the MT101 -> pain.001 mapping.
Changed¶
Joined the suite’s single version line,
0.0.2->0.0.60. Every package in thepain001suite now ships the same version number, so there is no compatibility table to consult. This package had been numbered independently and reached0.0.2against a0.0.60core; both were defensible under the previous policy, but a user could not tell that apart from drift. Versions advance in0.0.1steps from here and stay on the0.0.xline —0.1.0follows0.0.999.0.0.3through0.0.59were never released for this package and never will be.
Added¶
Benchmarks and a scaling guard (
tests/test_benchmarks.py), run in CI with results kept as an artifact. The guard compares the parser against itself at 1000 and 4000 transactions rather than using a wall-clock threshold, so it is independent of runner speed; it was checked against the failure it exists for by injecting a per-transaction rescan, which moves the ratio to 11.3x against a ceiling of 8.
0.0.2 - 2026-07-18¶
Changed¶
Require
pain001 >= 0.0.55, < 1(was>= 0.0.53, < 1) to propagate a security fix released in thepain001core library. No API or mapping changes in this loader.
0.0.1 - 2026-07-12¶
Added¶
First release of pain001-loader-mt101, a SWIFT MT101 → ISO 20022
pain.001 converter and the second deliverable of the MT→MX converter
project (after
pacs008-loader-mt103).
Companion to the
pain001 core library.
Public API: a single function parse_mt101(text) that returns a
list[dict] — one record per sequence-B transaction — whose keys are
exactly the flat-record fields pain001 validates against the
pain.001.001.09 JSON schema, so the records feed straight into
pain.001 generation.
Mapped MT101 fields¶
:20:Sender’s Reference →id+payment_information_id:30:Requested Execution Date →requested_execution_date+date(SWIFT sliding year window;YYMMDD→YYYY-MM-DD):21:Transaction Reference (seq B) →payment_id:32B:Currency + Amount (seq B) →currency+payment_amount(SWIFT comma-decimal handled; no value date, unlike MT103:32A:):50a:Ordering Customer →debtor_name,debtor_account_IBAN,initiator_name:52a:Account Servicing Institution →debtor_agent_BIC:57a:Account With Institution (seq B) →creditor_agent_BIC:59a:Beneficiary (seq B) →creditor_name,creditor_account_IBAN:70:Remittance Information (seq B) →remittance_information:71A:Details of Charges (seq B) →charge_bearer(OUR→DEBT,BEN→CRED,SHA→SHAR)Message-level:
nb_of_txs= count of sequence-B blocks,ctrl_sum= total of all amountsSynthesised defaults:
payment_method=TRF,batch_booking=False,service_level_code=SEPA,charge_bearerfallback =SLEV,remittance_informationfallback =NOTPROVIDED
Quality gates¶
100% line + branch coverage enforced via
--cov-fail-under=100.100% docstring coverage enforced via
interrogate.Type-checked with
mypy --strict; linted withruff; formatted withblack.Parsed records are verified schema-valid against the real
pain001SchemaValidator("pain.001.001.09")in the test suite.