Measured Behaviour

Does obfuscation break backflow prevention testing?

Every other area we measured this pass shares an arrangement that is easy to mistake for a law of nature: the caller sets the strict value and the library ships the permissive one, so losing a name loosens the control. This one is built the other way up on purpose - the utility denies by default - and almost every result inverts. Including one that gets worse when the rename pattern gets wider.

A programme that classifies deny-by-default

A cross-connection control programme decides three things about every service connection: what hazard the premises presents, what backflow assembly that hazard requires, and how often the assembly must be tested. All three are lookups, and the interesting question in every lookup is what happens when it misses.

Our utility has done what good practice says: it classifies the uses it has assessed - hospital, mortuary, vehicle wash, dental and so on - and sets the fallback for anything it has NOT assessed to HIGH hazard. A premises nobody has looked at is treated as dangerous until somebody says otherwise. The library it hands that configuration to defaults the other way, to LOW, because a register that cannot know your jurisdiction cannot classify a premises it has never heard of as hazardous.

That single decision inverts most of what follows, and it is the reason this area is in the pass at all. A finding that only holds when the caller is the strict one is not a finding about renaming; it is a finding about that arrangement.

Eight connections, three of which need action

A hospital with the assembly its hazard requires, tested this year. A MORTUARY fitted with a double check valve, which is not enough for a high hazard. A VEHICLE WASH with the right assembly and a test five hundred days old against a one-year interval plus thirty days of grace. A dental surgery, a restaurant, an office and a dwelling, all correct. And a RESEARCH LABORATORY, which is a use the utility has never classified - so it falls to the high-hazard default, needs a reduced-pressure zone assembly, and has a dual check.

The correct run: five compliant, three failing, all three disconnected, and nobody left downstream of an unactioned cross-connection. The mortuary, the vehicle wash and the laboratory have 620, 310 and 870 people behind them on the distribution main.

The classification table makes it stricter, not looser

Rename the option carrying the hazard classification table and every use falls to the utility's own high-hazard default. COMPLIANT drops from 5 to 2 and FAILING rises from 3 to 6. The office, the dwelling and the restaurant are suddenly under-protected on paper, because a dual check is not enough for a high hazard.

Read what that means before moving on. This is a rename that makes the run HARSHER: three connections that are genuinely fine are marked for disconnection. It is expensive, it is wrong, and it is exactly the kind of failure a team notices within a day, because three customers ring up. Nobody is left exposed - the counter reads zero.

Renaming the PREMISES USE FIELD on the records produces identical counters, for the identical reason: a use the table cannot find falls to the same default. Two halves of one lookup, one direction. So does the union of both.

The fallback, and a union worse than either half

Rename the option carrying the FALLBACK instead and it reverts to the library's LOW. Only one connection is affected - the laboratory, the one premises the deny-by-default rule existed for. COMPLIANT goes 5 to 6, FAILING 3 to 2, and 870 people are downstream of a high-hazard cross-connection that was left in service with a dual check on it.

Now rename BOTH. Nothing is classified, and the default for anything unclassified is the permissive one. Every connection in the register is a low hazard, a dual check satisfies a low hazard, and the one-year test interval becomes five years, so the vehicle wash's five-hundred-day-old test is in date. COMPLIANT is 8. FAILING is 0. Nothing is disconnected. 1,800 people are downstream of the three connections that needed action.

This is the cell worth taking away from the article. One half fails CLOSED and noisily. The other half fails open on a single premises. The union is worse than either, and it is the arm a realistic broad pattern actually produces. A matrix in which one half looks over-strict and the other looks like a minor edge case is not a matrix that tells you the union is fine.

The interval, the grace period, and a date that will not read

The test interval behaves the same way as the hazard classification, and for the same structural reason. Renaming the per-hazard interval table puts everything on the utility's one-year catch-all, which makes the office and the dwelling - legitimately on a five-year interval - overdue. FAILING goes 3 to 5. Stricter, and loud. Rename the catch-all as well and everything goes to the library's ten years: the vehicle wash's old test is in date, FAILING drops to 2, and 310 people are downstream of an untested high-hazard assembly.

Renaming the grace period alone does it too. Thirty days becomes the library's three hundred and sixty-five, five hundred days is inside a year plus a year, and the same 310 people appear on the counter.

And then the record side. Rename the LAST TEST DATE and the arithmetic that computes how long ago the test was produces NaN. The overdue test asks whether that figure is greater than the interval plus the grace - a ceiling, phrased as 'is this too long ago' - and every comparison against NaN is false. The finding is skipped. FAILING drops to 2 and the same 310 people appear. Not one date is wrong in the register; the register prints them. What is missing is the ability to compare them.

The check that catches it, and the flag that turns the check off

The utility's own rule is a good one: every connection must be accounted for, and every failing connection must have been acted on. Rename the option that disconnects failing connections and the rule fires - three failing, only zero acted on - and the run reports failure. The guard works.

Rename that option together with the flag that switches the rule on, and the COUNTERS ARE BYTE-IDENTICAL. Five compliant, three failing, zero disconnected, 1,800 people exposed. The only difference between the two runs is that one says backflow-rejected and the other says 'checked by unchecked'.

We are pointing that out because it is a measurement caveat as much as a finding. If you audit these arms by diffing counters - which is the obvious, cheap, mechanical thing to do, and what we do first - these two arms are the same arm. The thing that distinguishes a loud failure from a silent one is not in the numbers. It is in whether anybody was told.

What to do about it

The narrow fix is the same as everywhere else in this series: scope your member-renaming regexp to the members your own model classes own. Every arm above is an option key on a configuration literal handed to a library, or a field name on a record that library reads.

The design lessons here are more specific than usual because the deny-by-default arrangement changes them. Setting your fallback to the strict value is still right - it is what turned four of these arms from silent into loud - but understand what it buys and what it does not. It protects you when the TABLE goes missing. It does nothing when the FALLBACK ITSELF goes missing, and that is one name on the same object.

So put the safety in a place a single pattern cannot reach both halves of. Validate the classification you computed against a list of permitted hazard values before you act on it, and refuse a run in which the number of distinct hazard classes collapsed to one - both of our worst arms produce exactly that signature. And when you write a staleness test, phrase the refusal so that an unreadable date fails the check rather than skipping it: require a valid test date to be present, then compare it, rather than comparing and hoping.

Frequently asked questions

Does renaming a hazard classification table always loosen the result?

No - in our fixture it did the opposite. Because the utility set its own fallback to high hazard, losing the table sent every premises to the strict default and took compliant connections from five to two. The direction is decided by whose default is being substituted.

What was the worst arm you measured in this area?

Renaming the classification table and the fallback together. Each half on its own is either over-strict or affects a single premises; the union marked all eight connections compliant, disconnected nothing, and left 1,800 people downstream of three connections that needed action.

Why does a missing test date skip the overdue finding?

Because the check asks whether the elapsed time is greater than the interval, and every comparison against NaN is false. The refusal is not triggered, so the connection reads as in date. The dates themselves are still printed correctly in the register.

Is deny-by-default still worth doing?

Yes, on our measurements - it is what turned four arms from silent into loud. But it protects you when the classification TABLE is lost, not when the FALLBACK is, and those are two names on one object that one pattern can reach together.

Can counter diffs distinguish a loud failure from a silent one?

Not always. Two of our arms produced byte-identical counters, and the only difference was that one run reported a rejection and the other reported 'unchecked'. Whether anybody was told is not a number in the output.

What does a member regexp have to avoid here?

Sweeping the options object you hand to the register. Every arm we ran was either a key on that literal or a field name on the connection records it reads; a regexp naming your own model members reaches neither.

What assertion catches the worst case?

Refusing a run in which the number of distinct hazard classes collapsed to one. Both of our worst arms produce exactly that signature, and validating the computed classification against a list of permitted values costs a single line.

Related reading