Measured, not asserted
Published
Every failure this series has measured so far ends in an answer that is wrong: a value missing, unreadable, in the wrong unit, taken over the wrong set, split the wrong way, read off the wrong row. A cached answer is none of those. It was computed correctly, from genuine entries, against the right limit, and it reconciles against the entries it summed. This test renamed the one field telling the rollup its data had moved, and a facility that had crossed the major-source threshold at 103.6 tons kept reporting the 82.4 it was correctly at before the stack test came back.
A threshold that is crossed by arithmetic, not by an event
A synthetic minor permit is a bargain. The facility accepts an enforceable cap below the major-source threshold, and in exchange it stays out of the heavier permitting programme. Staying inside that bargain is a rolling calculation: every month, sum the last twelve months of emissions for the source and compare against the cap. Nothing happens on a particular day. The threshold is crossed by a sum changing.
The fixture is a coating line under a 95 ton per year cap, with the major-source threshold at 100. Fifteen months of records sit in the ledger; twelve of them are the period in force. As first estimated, using published emission factors, the twelve-month total is 82.4 tons -- comfortably inside the cap, and correct.
Then the laboratory returns a stack test. The measured emission factor for the high-VOC campaign run in two of those months is 2.8 times the published default they were estimated with. Those two entries are corrected, and the twelve-month total becomes 103.6 tons: over the cap the facility promised, and over the threshold that triggers a major-source application.
The rollup engine is copied in unprotected. It memoises, which any engine asked for this figure on every dashboard load will do, and it takes the caller's word for which fields decide that a cached answer has expired. Here the caller names two: the source, and the revision of the data behind it.
Protection on its own moved nothing
Twenty-five comparisons across five areas and five presets -- the ES5 default path, the modern target, the emit gate's option set on both targets, and the string transforms -- every protected run identical to the unprotected one, with each original run twice before anything was compared to it.
Everything below required member renaming that reached names shared with the installed rollup engine.
An answer that was true, and is served again after it stopped being true
Rename the data revision field and the second rollup finds its own earlier answer under an unchanged key. The facility reports tons=82.4 cap=95 major=100 => WITHIN THE CAP after the stack test that put it at 103.6.
Nothing about that total is fabricated. Twelve genuine monthly entries produced it. The cap is right, the threshold is right, the twelve-month window is right, the source is right. An inspector who recomputed the figure from the ledger would get 103.6 and an inspector who read the reported figure would get 82.4, and the difference between them is not an error in the arithmetic. It is the date the arithmetic was done.
The same outcome arrives from the option side. Renaming the key that carries the list of cache-key fields reverts the engine to its own default of keying on the source alone, and the result is identical -- with one difference that matters for auditing. The record-side rename leaves a visible tell: the key prints as EU-COATING-1|undefined@15. The option-side rename prints EU-COATING-1@15, which is exactly what a correct one-field key looks like. There is no undefined anywhere on the line.
The reconciliation caught it, and the reason it did is a design decision
This is the part of the pass worth carrying away, because it inverts what the previous three passes concluded.
The facility's rule of record is the check an auditor would actually ask for: the reported total must reconcile against the entries it was summed from. In every earlier pass, a reconciliation of that shape has been closed by construction and passed while the answer was wrong. Here it fired: rollup-rejected(rollup-check(total 82.4 does not reconcile against 12 entr(ies) summing 103.6)).
It fired because the cache holds references to the live ledger records rather than a snapshot taken alongside the total. When the stack test corrected those two entries, the cached total stopped agreeing with the very entries cached beside it, and the check saw the disagreement. Had the engine copied the entries into the cache -- which is the more defensive-looking implementation, and the one most people would write -- the cached total and the cached entries would have agreed perfectly forever and the check would have passed.
So the mitigation is real, and it is real for a reason nobody chose deliberately. State it as a rule: a reconciliation can only detect a stale answer if it compares that answer against the records as they are now, never against a copy taken when the answer was computed.
And the two ways the check stops firing
Both are one line away. Renaming the data revision together with the flag that enables the check produces SERVED-FROM-CACHE entries=12 tons=82.4 cap=95 major=100 => WITHIN THE CAP, unchecked. Renaming the cache-key option together with the caller's rule function produces the same total with checked by library-builtin(accepts any rollup) -- the word "checked" survives, and what it now names is the library's own rule, which accepts anything.
Two adjacent keys in one options object are one blast radius, not two controls. That has now been measured in four consecutive passes and it is the single most reliable way a well-designed mitigation is removed: not by defeating it, but by switching it off with the same edit that creates the thing it was there to catch.
The rest of the area, including the mirror
Renaming the monthly tonnage field produced non-finite-emissions(refused before rollup) -- the value fails closed and loudly, for the sixteenth shape running in this series, while the meaning fails open and quietly.
Renaming the rolling window reverted it to the library's one-month default: entries=1 tons=7.2 => WITHIN THE CAP, and the reconciliation passed truthfully, because 7.2 really is the sum of the one entry it used. A twelve-month total understated by 93% with a check certifying it.
The two limits are worth separating. Renaming the permit cap alone still produced TITLE V APPLICATION REQUIRED, because the major-source threshold survived and caught it. Renaming the threshold alone downgraded the finding to PERMIT CAP EXCEEDED. Renaming both put 103.6 tons under cap=Infinity major=Infinity and reported WITHIN THE CAP. Each half alone looks like a partial loss a reviewer would close as cosmetic; the union is the finding disappearing.
Renaming the month field went the other way and pulled the three months outside the period back in: entries=15 tons=109.3, an over-statement that reports a threshold crossing that has not happened. Wrong, and safe.
What this means if you protect a compliance or reporting front end
A stale answer is the hardest of these shapes to test for, because every static property of it is correct. It has the right shape, plausible magnitude, a valid provenance and an internally consistent audit trail. The only thing wrong with it is a relationship between two moments in time, and no assertion about the answer alone can see that.
In practice: keep member renaming off the boundary with a MemberRegexp scoped to your internal names; treat any field that participates in a cache key as load-bearing, because it is doing work no other field does and it does not look like it; and make your reconciliation read the source records live rather than a snapshot stored with the result. That last one costs nothing and it is the only check in this article that caught anything.
The reporting-obligation framing in SEC cyber disclosure and your JavaScript is the same problem in a different register: a duty that attaches when a number crosses a line is only as reliable as the moment the number was last taken. Protection did not cause any of this -- the protected build reported both rollups correctly on all five presets -- but knowing which of your names cross a boundary is what keeps it that way.
Frequently asked questions
Did obfuscation change any reported total on its own?
No. Five areas through five presets, twenty-five comparisons, every protected output byte-identical to the unprotected run. Everything in this article required member renaming aimed at names the installed rollup engine also reads.
What is different about a stale answer compared with a wrong one?
Every static property of it is correct. The total is a genuine sum of genuine entries against the right limit over the right window for the right source. What is wrong is a relationship between two moments: it is the answer to the state the data was in before the stack test. No assertion about the answer alone can see that.
How did renaming one field produce it?
The engine memoises the rollup and the caller names which fields mean a cached answer has expired -- here the source and the revision of the data behind it. Rename the revision and every state of the data shares one key, so the second rollup found the first one's answer: 82.4 tons reported after the corrected figure had become 103.6.
Did anything catch it?
Yes, and this is the first pass in several where the obvious reconciliation worked. The facility's rule refused a total that does not reconcile against the entries it summed, and it fired -- because the cache holds references to the live records. Had it cached a copy of the entries, the total and the entries would have agreed forever and the check would have passed.
So the mitigation is safe to rely on?
Only in that shape. It stopped firing in two arms, both one line away: renamed together with the flag enabling it, the report reads WITHIN THE CAP and unchecked; renamed together with the caller's rule function, it reads checked by the library's own builtin, which accepts anything. Two adjacent keys in one options object are one blast radius.
Which names failed safely?
The monthly tonnage, which refused the rollup outright as non-finite, and the month field, which pulled three months from outside the period into the total and over-stated it. Losing a value fails closed and loudly; losing what a value means fails open and quietly.
What is the cheapest test that would have caught this?
Compute the rolling total twice with a change to the underlying records in between, and assert that the second answer differs. A test that computes it once and checks the figure is correct passes in every arm in this article.
Related reading