Skip to content

6.1: Trade identifier sources and the optional Bogus integration - #14

Merged
holonsoftFounder merged 5 commits into
mainfrom
feature/6.1-trade-identifiers-and-faker
Sep 21, 2026
Merged

holonsoftFounder merged 5 commits into
mainfrom
feature/6.1-trade-identifiers-and-faker

Conversation

@holonsoftFounder

Copy link
Copy Markdown
Member

What is in here

  • New data sources in holonsoft.AutoPoco.DataSources.Identifiers: GTIN-8/12/13/14 (plus Ean13Source), SSCC, ISBN-10/13, ISSN, ISIN, IMEI and ASIN, each with a valid check digit where the format has one, each with a Nullable... variant. Check digit algorithms live in the internal CheckDigits helper and are pinned by tests with independent reverse-direction validators.
  • TestBinCreditCardSource: card numbers built on the six digit test BINs the payment processors publish, so generated data is recognisable as test data.
  • holonsoft.AutoPoco.Faker: a separate, optional package that bridges to Bogus for names, addresses, companies, product names, prices, currency codes and dates. The AutoPoco session seed drives Bogus through a randomizer on our own StableRandom; the Bogus version is pinned exactly because its locale data decides the values for a seed.
  • Two CreditCardSource fixes, both change the stable sequences once:
    • The Luhn check digit was calculated with the doubling shifted by one position, so no generated number passed a real Luhn validation.
    • Only the first digit of the scheme was fixed, so an "American Express" could be detected as a Diners Club and a "MasterCard" could start with 56. Prefixes are now drawn from the ranges the schemes really issue in (34/37, 51-55 and 2221-2720, 6011/644-649/65, 4).
  • CI and publish now test the whole solution; publish verifies that both packages carry the tag version.

Verification

  • dotnet build -c Release: zero warnings.
  • dotnet test on net8/9/10: 3867 passed, 12 known skips.
  • dotnet pack: both nupkgs produced; the Faker package carries its own README, the exact Bogus pin and the dependency on the core package.
  • Scheme detection in the tests is calibrated against published card numbers (including Diners Club and JCB as negative cases) before it judges the source.

No release with this PR; the publish workflow only runs on a v* tag.

🤖 Generated with Claude Code

holonsoftFounder and others added 5 commits September 21, 2026 16:15
New sources in DataSources/Identifiers, each with a nullable variant:
GtinSource (GTIN-8/12/13/14), Ean13Source, IsbnSource (ISBN-10 and
ISBN-13), AsinSource, SsccSource, IssnSource, ImeiSource and IsinSource.
A GTIN, an SSCC and an IMEI take an optional prefix, so a whole catalogue
can share one GS1 company prefix or one type allocation code.

The check digit algorithms moved into Util/CheckDigits (Gs1Mod10,
Mod11Descending and Luhn), so a source that needs one no longer reaches
into another source to get it. An ISBN-13 and a GTIN-13 share the GS1
mod 10, an ISSN and an ISBN-10 share the descending mod 11, and a credit
card, an IMEI and an ISIN share the Luhn.

CreditCardSource produced numbers that fail the Luhn check. The
validation weights were applied to a number that had no check digit yet,
so every digit was weighted one position off and not one generated card
passed a real validator. Fixed, which changes the sequences the tests
pin. The partial number 411111111111111 now closes to
4111111111111111, the published Visa test number, instead of ...115.

TestBinCreditCardSource builds on the first six digits of card numbers
that payment processors publish for their test environments, so its
output is recognisable as test data rather than possibly being somebody's
card. Those prefixes are an industry convention, not a range reserved by
a standard; ISO/IEC 7812 has none for cards. CreditCardSource keeps
drawing everything behind the scheme digit, so the old behaviour and its
collision risk stay available on purpose.

IsbnSource only produces registration groups that are actually handed
out. It used to draw the group digit freely, which put numbers into
979-0, the ISMN range of sheet music that never carries an ISBN.

Every algorithm is pinned against published numbers rather than against
itself: real EAN-13s and UPC-As, the ISBN-10 of The C Programming
Language, four real ISINs, two published IMEIs, two real ISSNs and the
test cards of Visa, MasterCard, American Express and Discover. The
validators in the tests weight the complete number, the other way round
from the generators, so a weight applied in the wrong direction shows up
as a mismatch instead of cancelling out.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
A separate package, so the core keeps its promise of having no
dependency. Bogus supplies the individual believable value, AutoPoco
keeps building the object graph, holding members apart and repeating the
whole thing for a seed. Bogus never builds an object here.

Fourteen sources, each with a nullable variant and a configurable locale:
first, last and full names, email addresses, phone numbers, street
addresses, cities, countries, postal codes, company names, product names,
prices, currency codes and dates.

The session seed drives Bogus. StableRandomizer derives from
Bogus.Randomizer and puts AutoPoco's own StableRandom in place of the
System.Random behind it, so a seed produces the same values on every .NET
version. FakerSourceBase builds one faker per source instance, lazily,
and drops it on every reseed, so each member keeps its own stream and a
second session starts from its own seed. The static Randomizer.Seed of
Bogus is never read and never written.

That last point needs a test that can actually fail. A Bogus randomizer
built from an int seed is deterministic as well, so every seed test would
pass even if the injection silently did nothing. The guard compares
against plain Bogus on the same seed and requires the two to differ;
removing the injection fails that one test and leaves the other
twenty-three green.

Bogus is pinned to exactly 35.6.5. Its values for a seed come from locale
data inside its package, so a Bogus update would change generated names.
The exact range means a project with another Bogus version gets a NuGet
conflict instead of silently different test data. For the same reason the
tests assert shape and repeatability and never a literal value.

Both workflows now run the tests of the whole solution. They named the
core test project, so the new suite would have been built and then never
run, and the release gate would have published a package whose tests had
not executed. The publish workflow also checks the version of the new
package before pushing, since it pushes everything in the artifacts
folder.

The Faker package carries its own README, otherwise its page on nuget.org
would open with the core AutoPoco documentation.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
A "New in 6.1.0" section for the trade identifiers and for the Faker
package, and release notes for both packages.

The documentation says where each guarantee stops, which is the part that
is easy to leave out: an ISBN stays inside an allocated registration
group but a GTIN without a prefix can land in a range GS1 reserves for
something else, the Faker sources are independent of each other so a city
and a postal code on the same object do not belong together, and a seed
reproduces Bogus values only as long as the Bogus version stays the same.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The README table and the release notes named only Gtin, Ean13, Isbn
and Asin. Add Sscc, Issn, Isin and Imei to both, describe
TestBinCreditCardSource, and state the Luhn fix of CreditCardSource:
its check digit was calculated with the doubling shifted by one, so
the numbers failed a real Luhn validation, and fixing it changed the
generated sequences once.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Only the first digit of the scheme was fixed, so an American
Express could start with 36 and be detected as a Diners Club, a
MasterCard could start with 56, which no scheme issues, and a
Discover landed almost anywhere in the 6 range. Now the prefix is
drawn from the real ranges: 34 and 37 for American Express, 51 to 55
and the 2 series 2221 to 2720 for Mastercard, 6011, 644 to 649 and
65 for Discover. The tests detect the scheme with the classic
validator patterns, calibrated against published card numbers, and
the stable sequences changed once.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@holonsoftFounder
holonsoftFounder merged commit f86d94e into main Sep 21, 2026
2 checks passed
@holonsoftFounder
holonsoftFounder deleted the feature/6.1-trade-identifiers-and-faker branch September 21, 2026 16:34
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