Skip to content

6.1: IBAN and VAT ID sources with real check digits - #15

Merged
holonsoftFounder merged 3 commits into
mainfrom
feature/6.1-iban-and-vat
Sep 21, 2026
Merged

holonsoftFounder merged 3 commits into
mainfrom
feature/6.1-iban-and-vat

Conversation

@holonsoftFounder

Copy link
Copy Markdown
Member

What is in here

Three sources in holonsoft.AutoPoco.DataSources.Identifiers, plus the check digit helpers they need (Mod97, Iso7064Mod1110, WeightedMod11 in the internal CheckDigits).

IbanSource / NullableIbanSource

  • Every SEPA country of the SWIFT IBAN registry (37 entries), electronic format without spaces, correct ISO 7064 mod 97 check digits.
  • National check digits inside the BBAN are calculated where the country keeps some: the Belgian mod 97 tail, the Spanish DC pair, the French/Monegasque RIB key, the Italian/Sammarinese CIN letter, the Norwegian, Estonian, Finnish, Hungarian, Polish and Icelandic schemes and the Portuguese and Slovenian ISO 7064 pairs. DK and SE have no reliably published account check algorithm, there the digit is drawn (documented in code).
  • Tests are calibrated against the official registry example of all 37 countries; a dedicated test builds numbers with recalculated mod 97 digits but broken national digits and expects rejection.

TestBlzIbanSource / NullableTestBlzIbanSource

  • German IBANs whose bank code starts with a nine: the Bundesbank assigns clearing areas one to eight only, and the current official bank code file (13,760 records) holds no code starting with nine. Recognisable as test data, can name nobody's account.
  • The README explains why this matters more for IBANs than for card numbers: a SEPA direct debit needs no second factor. No such variant exists for AT/CH because no unassigned range is published there.

VatIdSource / NullableVatIdSource

  • 20 prefixes with a valid check digit: AT, BE, DE, DK, EE, FI, GB, HR, HU, IE, IT, LT, LU, NL, PL, PT, SE, SI, SK, XI.
  • Every algorithm is calibrated against the official worked example of the BMF construction rules document (or, for HR and the first six countries, registered real-company numbers), including the tricky ones: the Lithuanian double weight pass, the UK MOD 97 / MOD 9755 pair with excluded ranges, the Irish check letter mod 23, the Danish and Slovak divisibility tests.
  • EL, ES, FR, CY, CZ, LV, MT, BG and RO have not agreed to publication of their rules and are left out on purpose; the README states the principle.
  • Along the way this identified a check digit bug in a third-party Austrian VAT implementation; ours follows the official BMF formula, verified against the BMF worked sample and ATU13585627.

Verification

  • dotnet build -c Release: zero warnings.
  • dotnet test on net8/9/10: 4518 passed, 12 known skips (~490 new tests for IBAN and VAT).
  • All validators in the tests run the arithmetic in the opposite direction of the generators (closure properties, check digit weighted into the sum) and are measured against official examples before they judge the source.
  • Mutation tests confirm no single digit change survives, except in the four VAT schemes (GB, XI, LT, PT) where the standard itself can accept a mutated number; those are excluded with the reason in a comment.

No release with this PR; tagging 6.1.0 follows separately.

🤖 Generated with Claude Code

christian.vogt@hiquaro.com and others added 3 commits September 21, 2026 18:48
Germany and Croatia run on ISO 7064 MOD 11,10, Austria on the BMF
digit sum with its 96 minus sum step, the Netherlands and Poland on
a weighted mod 11 and Italy on Luhn with the office code kept in the
range that is handed out. The tests are calibrated against twelve
registered VAT IDs of real companies and the worked example of the
BMF specification before they judge the generator, and the
validators run the arithmetic in the opposite direction: ISO 7064
via its closure property, the weighted schemes with the check digit
weighted minus one.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The structures come from the SWIFT IBAN registry, the mod 97 check
digits from ISO 7064, and where a country keeps its own check digits
inside the BBAN they are calculated as well: the Belgian mod 97
tail, the Spanish DC pair, the French and Monegasque RIB key, the
Italian and Sammarinese CIN letter, the Norwegian, Estonian,
Finnish, Hungarian, Polish and Icelandic schemes and the Portuguese
and Slovenian ISO 7064 pairs. The tests are calibrated against the
official registry example of all thirty seven countries and verify
every national check the other way round, with the check digit
weighted into the sum; a constructed number with fresh mod 97 digits
but broken national digits has to fall through.

TestBlzIbanSource builds German IBANs on bank codes starting with a
nine: the Bundesbank hands out the clearing areas one to eight only
and the current official bank code file holds no code starting with
a nine, so the number provably names nobody's account. The README
says clearly why that matters more for IBANs than for card numbers:
a SEPA direct debit needs no second factor.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Thirteen more prefixes from the official BMF construction rules
document, each calibrated against its worked example: BE (mod 97
pair), DK and SK (divisibility by eleven with a redraw when no last
digit fits), EE (weights 3, 7, 1 behind the fixed 10), FI (the
unusual weights 7, 9, 10, 5, 8, 4, 2), GB and XI (MOD 97 and
MOD 9755 with their excluded ranges), HU (weights 9, 7, 3, 1), IE
(check letter mod 23 in the eight and nine character forms), LT (the
double weight pass whose worked example exercises the fallback), LU
(mod 89 pair), PT and SI (mod 11 with their asymmetric special
cases) and SE (Luhn over the organisation number plus the 01 to 94
suffix). EL, ES, FR, CY, CZ, LV, MT, BG and RO have not agreed to a
publication of their rules and stay out on purpose. The mutation
test skips GB, XI, LT and PT, whose schemes can legitimately accept
a mutated number; everywhere else no single digit change survives.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@holonsoftFounder
holonsoftFounder merged commit cdda279 into main Sep 21, 2026
2 checks passed
@holonsoftFounder
holonsoftFounder deleted the feature/6.1-iban-and-vat branch September 21, 2026 18:57
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant