Measured, not asserted
Published
Every rule in an approved-supplier programme is cumulative over a supplier. Three major non-conformances in the window suspends one. A certificate covers one site of one. But the records are not the suppliers -- they are sightings of suppliers, arriving from purchasing, from the certification body and from the inspection database under three spellings of the same name. How many suppliers there are is the output of a match, and it is the one figure no reconciliation is defined over. This test moved it in both directions without changing a single other number.
Ten records, six suppliers, and one number nobody checks
The fixture is a supplier master holding ten records. Northfield Produce arrives three times under three spellings of one name for one site, carrying two, one and one major non-conformances -- four in total, which is over the limit of three, so that site must be suspended. Ribera Citrus holds two sites: Murcia is certified to day 610, Almeria's certificate lapsed on day 55 and it must not ship. Baltic Oils has lapsed too. Clonmel and Vallee Verte are fine.
The correct answer is six suppliers from ten records: three approved, one suspended, two not approved on a lapsed certificate. Ten records attached, seven major non-conformances in the book, and the manufacturer's own approval rule signing it off.
Rename the option that says whether names are folded before they are matched. The library falls back to comparing them exactly as they arrived, and the three spellings of Northfield stop being the same supplier.
The measured result: suppliers=10 records=10 of 10 major-nc-total=7 foots=true approved=7 suspended=0 lapsed=3. The suspended supplier is approved. And every other figure on that line is identical to the correct run.
Why every check passed
The manufacturer's approval rule is not a weak rule. It requires every record that arrived to be attached to some supplier, and it requires the non-conformance total to survive the merge. Both are exactly the kind of reconciliation this series has spent many passes recommending.
In the failing arm it prints: approval-check(10 record(s) attached, 7 major non-conformance(s) carried through the merge). In the correct arm it prints the same sentence, word for word.
That is not a coincidence and it is not a bug in the rule. Merging records into entities neither creates nor destroys a record, and it neither creates nor destroys a non-conformance. It redistributes them. A conservation check is about totals, and the quantity that moved here is a count of things -- a cardinality -- which is exactly what conservation cannot see.
Earlier passes in this series established that a reconciliation closed by construction proves nothing about a split, an allocation or a classification. This adds the sharpest case yet: the failing quantity is not a total at all, and no assertion over totals can reach it.
The mirror, on the same object, in the opposite direction
Losing the folding splits one supplier into three. Losing a part of the match key does the opposite. Rename the site-code field on the records and the two Ribera sites collapse into one supplier.
The result: suppliers=5 major-nc-total=7 foots=true approved=3 suspended=1 lapsed=1. The suspension still fires correctly. The non-conformance total is still seven. The record count still foots. What changed is that a site whose certificate expired on day 55 now sits inside an entity whose certificate runs to day 610, because an entity's certificate is the latest one anybody holds for it. Almeria ships under Murcia's certificate.
So the two directions come from one object and fail opposite ways, and they are detected by different parties. An over-split under-punishes: nobody is suspended, and the only party who would notice is the auditor who counts your suspensions. An over-merge propagates one site's credentials to another, and the party best placed to notice is the site that benefits.
A compound key is robust, and the condition is not the one you would guess
The programme matches on tax identifier, legal name and site code together. Renaming any one of those on the records -- the tax identifier, or the legal name, or both -- produced an answer identical to the correct one. Six suppliers, three approved, one suspended, two lapsed. Renaming all three at once collapsed the book to a single supplier and was loud and obvious.
The obvious reading is that redundancy protects you. That reading is wrong, and a purpose-built experiment is what showed it. A compound key separates two entities only while the parts you still have disagree, and whether they do is a property of your book, not of your key.
The experiment built the shape the base fixture happened not to contain: two unrelated companies packing out of one shared third-party site. Losing the tax identifier there still separated them, because their legal names differ. Then it built one company running two production halls at one address, where the records agree on the tax identifier and on the legal name and the site code is the only part holding them apart. Losing the site code merged them, and the hall whose certificate lapsed on day 80 was approved under the other hall's certificate to day 610 -- with the approval rule still printing two records attached and one non-conformance carried through. Identical on both member presets, run through the real engine rather than a simulated rename.
So the prediction that a redundant key is safe failed, and the prediction that losing any key part is dangerous failed too. What is true is narrower and more useful: the risk lives wherever one part of the key is the only thing distinguishing two entities, and shared sites, renamed companies and multi-hall operations are exactly where that happens.
Protection on its own moved nothing
As with every area this pass, the five presets came first: the ES5 default path, the modern target, the emit gate's option set on both targets, and the string transforms. Twenty-five comparisons across the five areas, all byte-identical to the unprotected run.
Everything above required member renaming reaching names the installed supplier-master library reads. The match keys are named in the configuration as text -- the strings for the tax identifier, the legal name and the site code -- and looked up on each record by that name. Renaming rewrites the name in code and leaves the text alone, which is why the configuration screen goes on reading match-keys=taxId+legalName+siteCode in every arm above.
The arms that failed loudly
The plain quantities failed closed, as they have in every shape this series has measured. Renaming the non-conformance count produced approval-rejected(approval-check(non-conformance total is not a number)) and nothing was assessed at all. Renaming the certificate expiry sent every supplier to not-approved: approved=0 lapsed=5, which is a fleet-stops-shipping failure that somebody escalates inside an hour.
That last pair is worth holding side by side. The certificate date and the non-conformance count are written on the same records as the name fields, in the same object literals. Lose a value and the programme stops. Lose the meaning -- how the records group into suppliers -- and the programme runs, reports, foots and approves the wrong list. The value-fails-closed and meaning-fails-open contrast now holds for the nineteenth distinct failure shape this series has measured.
Renaming the suspension limit is the arm most people would expect to be the dangerous one. It is not silent in the way the matching arms are: the supplier count stays correct at six, so a scorecard that lists suppliers still lists six, and only the suspension is missing. It is the arm where somebody asking 'why has nobody been suspended this quarter?' gets an answer.
Why the entity count is invisible
Ask what a supplier-approval report is checked against and the answer is almost always the records that fed it. Did every record land somewhere? Do the non-conformances add up? Are the certificates in date? All three are answerable from inside the system and all three are true in the failing arms.
The number of suppliers is different in kind. It is not carried in from anywhere -- it is manufactured by the match. There is no external quantity it is compared with, which is why it can move from six to ten, or from six to five, without a single downstream figure flinching.
There is an external source, though, and most food manufacturers already have it: the certification body publishes a list of certified sites, and the purchasing system knows how many suppliers it raises orders against. Either of those is outside the match, and either would have failed.
What to assert
Assert the cardinality against something outside the match. The number of distinct suppliers after resolution should equal the number your certification scheme or your purchasing ledger says you have, and a difference is an event that needs a person, not a rounding difference.
Assert one known duplicate group end to end. Put a supplier in your fixture that arrives three times under three spellings and assert two things: that it resolves to one supplier, and that its cumulative non-conformance count crosses the threshold and produces a suspension. That fails in the folding arm, in the match-key arm and in their union.
Assert one known distinct pair too, because the merge direction is the one that hands credentials to the wrong site. Two entities that differ in exactly one key part must stay two.
And treat a cumulative rule as needing a completeness precondition. A supplier assembled from fewer source systems than you expect is not necessarily a supplier with a clean record; it may be a fragment of one. That check is worth having whether or not anything is ever renamed -- a dropped column over an integration hop produces the same split.
For the obfuscation side specifically, the fix is the ordinary one: exclude the property names that cross into the supplier-master library, and keep a duplicate-resolution test that would fail if the exclusion were removed. Suppliers are also where the Cyber Resilience Act puts its weight, and a supplier list that silently doubles in length is a poor foundation for that reporting.
Frequently asked questions
Did obfuscation on its own break supplier approval?
No. Five presets across all five areas of this pass produced output byte-identical to the unprotected run. Every result in this article required member renaming reaching names the installed library reads.
What exactly moved when the folding option was renamed?
Only the number of suppliers. Ten records stayed ten records, seven major non-conformances stayed seven, the ledger still footed, and the three spellings of one supplier became three suppliers -- none of which reached the limit of three.
Why did the manufacturer's own approval check pass?
Because it reconciles records and non-conformance totals, and merging records changes neither. It printed the same sentence in the failing arm as in the correct one: ten records attached, seven non-conformances carried through the merge.
Can the same rename fail the other way?
Yes, from the same object. Renaming the site-code field merged two sites of one company, and the site whose certificate had lapsed was approved under the other site's certificate. The suspension still fired and every total stayed correct.
Does a compound match key protect against this?
Only while the key parts you still have disagree. Renaming any single part of a three-part key left the fixture's answer correct; a purpose-built experiment with two halls at one address, differing only in site code, merged them and approved an uncertified hall.
Which arms failed loudly?
Renaming the non-conformance count refused the whole assessment as non-numeric, and renaming the certificate date sent every supplier to not-approved. Values fail closed; the meaning of how records group fails open.
What is the cheapest test that catches this?
One known duplicate group asserted to resolve to one supplier and to trigger its cumulative suspension, plus a check that the resolved supplier count matches an external roster such as your certification scheme's list of certified sites.
Related reading