Measured Behaviour
Published
A number in the wrong unit is a perfectly good number. That is why the plausibility check that catches everything else is blind to it, and it is why a gas test is a useful place to measure what a rename costs - along with oxygen, the one analyte that carries a limit in both directions.
Ten spaces, five ways to be refused
We built an entry day the way one runs: ten confined spaces, four analytes each, a band table, a declaration of what unit this site's meter reports in, a conversion factor per gas, a required test order and a thirty-minute retest window.
The bands are the real ones. Oxygen between 19.5 and 23.5 percent by volume - below and you asphyxiate, above and everything in the space becomes flammable. Flammable gas at ten percent of the lower explosive limit. Carbon monoxide at twenty-five parts per million, hydrogen sulphide at ten.
The correct run permits three entries and refuses seven, by five different mechanisms: a nitrogen-purged vessel at 19.1 percent oxygen, a space at 24.2 percent where an oxygen hose has been leaking, a space at fifteen percent of the explosive limit, a space at forty parts per million of carbon monoxide, a set of readings ninety-five minutes old, and a space where the flammable sensor was read before oxygen was confirmed. That last one matters because a catalytic-bead sensor needs oxygen to burn the sample, so a flammable reading taken first is not a low reading - it is a meaningless one.
Protected with default settings on all five profiles, behaviour was identical. Nothing below came from obfuscation on its own.
Twenty times smaller, and entirely plausible
This site's flammable meter reports percent by volume, because it is a laboratory-grade instrument. The library's canonical unit for flammable gas is percent of the lower explosive limit. For methane those differ by a factor of twenty.
Rename the unit declaration and the library does the only thing it can: it takes the number at face value in its own unit. A reading of 0.75 percent by volume - fifteen percent of the explosive limit, half again over the entry ceiling - is read as 0.75 percent of the explosive limit, which is comfortably safe. Entry is permitted.
Measured: permitted went from three to four and out-of-band refusals from five to four. Two other names produce exactly the same result by different routes - renaming the conversion-factor table, and renaming the key naming which gas is being tested for. In those the reading is not converted wrongly, it is dropped entirely and never compared. Three unrelated names, one identical outcome, and one crew inside a space at three times the limit.
No plausibility bound helps here. 0.75 is a reasonable figure in either unit, and it is inside every range the analyte has ever occupied. The mitigation is a design change worth making anyway: never let a unit live in a different key from the number it describes, and normalise at the boundary where the reading enters.
One band, two halves, four times the blast radius
Oxygen is the only analyte on a gas test with limits in both directions, which makes it the cleanest possible test of whether the two halves of a band behave alike. They do not.
Renaming the floor moves one entry. The nitrogen-purged vessel at 19.1 percent is entered; permitted goes from three to four. Every ceiling refusal survives untouched.
Renaming the ceiling moves four. Permitted goes from three to seven and out-of-band refusals from five to one. The oxygen-enriched space at 24.2 percent is entered, and so are the flammable space, the carbon-monoxide space and the hydrogen-sulphide space. Only the oxygen floor refusal survives.
Same object, adjacent lines, same type, both branches refusing - and one half is four times the other. The reason is not the direction of the comparison. It is that oxygen is the only analyte with a floor while every analyte has a ceiling, so the blast radius of losing half a band is the number of records that half governs. Two halves of one table can differ by a factor of four, and nothing about their shape tells you which is which.
Losing the whole band table permits eight of ten and drives out-of-band refusals to zero. Losing the test order permits the space that was read out of sequence. Losing the retest window permits the entry on ninety-five-minute-old readings.
The check reads better in the failing arm
The entry supervisor's rule counts entries, permitted, refused and out-of-band. It passes in every arm above.
Worse than passing, it improves. The correct run prints three permitted, seven refused, five outside a band. The unit-loss arm prints four permitted, six refused, four outside a band. A day with fewer atmospheric refusals reads like a well-ventilated site, and a reviewer scanning for anomalies stops on the run that looks worse - which is the correct one.
The loud contrast is one field away. Rename the reading value itself and the run refuses before anyone gets near a space, reporting ten of ten entries with no readable atmosphere. Losing a value fails closed. Losing what a value means fails open.
What to do about it
Carry the quantity with its unit rather than in a neighbouring key, or convert at the instrument boundary so that only one unit ever exists inside the application. A unit separable from its number is the whole precondition, and a hand-edited config or a serialisation hop that drops a key produces the same failure without any obfuscator involved.
Assert which limit was applied rather than whether the value looks sensible, and assert both halves of a two-sided band separately - they are not mirror images and this measurement shows they are not even the same order of magnitude.
On the protection side, scope the pattern. Protect Members documents how MemberRegexp selects members, and a reserved list is the right home for anything that names a unit, a limit or an analyte. If the readings come off a device rather than a keyboard, medical-device JavaScript compliance covers the same instrument-boundary problem in a regulated setting.
Frequently asked questions
Did obfuscation change any entry decision on its own?
No. On all five profiles - the ES5 target, the modern target, both emit-gate configurations and the string-encoding profile - the protected bundle behaved identically to the original. Every difference came from member renaming reaching the band table, the unit declaration or the reading records.
What did renaming the unit declaration do?
A flammable result of 0.75 percent by volume was read as 0.75 percent of the lower explosive limit - twenty times smaller for methane. A space actually at fifteen percent of the explosive limit, half again over the entry ceiling, was permitted.
Can a plausibility check catch a wrong unit?
No, and not by bad luck. 0.75 is a perfectly reasonable figure in either unit and sits inside every range the analyte has ever occupied. A number in the wrong unit is still a good number, which is what makes range checks structurally blind to it.
Are the two halves of the oxygen band equally risky?
No. Losing the floor moved one entry; losing the ceiling moved four. Oxygen is the only analyte with a floor while every analyte has a ceiling, so the blast radius is the number of records each half governs, not the direction of the comparison.
Did the entry supervisor's check catch any of it?
No, and it read better in the failing arm. The correct run prints three permitted and five outside a band; the unit-loss arm prints four permitted and four outside a band, which looks like a well-ventilated day.
What happened when the reading values were renamed?
The run refused before anyone approached a space, reporting ten of ten entries with no readable atmosphere. Losing a value fails closed and loudly; losing what the value means fails open and quietly.
What should we change in the code?
Carry the quantity together with its unit rather than in a separate key, or normalise at the instrument boundary so only one unit exists inside the application, and assert which limit was applied rather than whether a value looks sensible. Scope the rename with MemberRegexp so the band table and the unit declaration are never candidates.
Related reading