Measured, not asserted

Does obfuscation break maintenance interval tracking?

An inspection interval is not a number. It is a set of numbers with the word 'whichever comes first' in front of it: calendar time, flight hours, landings. Lose one member of that set and the remaining comparisons stay arithmetically perfect, the item is still measured against real limits, and the status that comes back is a correct answer to a question nobody asked. This is the one area of the pass where the recommended mitigation went six for six -- and the flag in front of it undid all six.

Whichever comes first is a set, not a number

The fixture is one airframe and three inspections, each of which can only be caught by one of the three criteria. One is 118.4 flight hours since it was last done against a 100-hour limit with a 10-hour tolerance, and is well inside its calendar and landing limits. One is 402 days against a 365-day limit with only 40 hours flown. One is 612 landings against a 500-landing limit at 61 hours and 120 days.

Correct answer: all three are overdue and the aircraft is grounded, each for a different reason. No criterion in that set is redundant, which is what makes losing one visible rather than academic.

Protection on its own moved nothing

Five areas, five presets, twenty-five comparisons, all identical to the unprotected run. Nothing in this article is caused by protecting the code, and the reproducibility guard ran each original twice before anything was compared to it.

One criterion out of three, and the item reads in limits

Renaming the flight-hours entry inside the interval set removed exactly one comparison. The engine examined two criteria instead of three, printed calendar 120/365d and cycles 140/500, found nothing exceeded, and would have reported the 118.4-hour inspection as IN-LIMITS with the aircraft AIRWORTHY.

It did not, because the operator's rule caught it. That rule is the mitigation this series arrived at two passes ago in its set-shaped form: refuse a status computed from fewer criteria than the item itself declares it is controlled by. Every item carries the number three; the engine examined two; the status was rejected with programme-check(examined 2 of 3 declared criterion(s)).

It caught the same failure from every route measured: the interval entry, the item's own last-done hours, the airframe's current hours counter, the calendar entry and the landings entry. Six routes, six catches. That is a better record than the same idea managed in the manufacturing pass, where it caught two of three and the miss was certified as complete by the check itself.

Then the flag in front of it went

The rule only runs if the operator switched it on. Renaming the interval entry and the enabling flag together produced maint AIRWORTHY=true ... examined 2 criterion(s) [calendar 120/365d, cycles 140/500] exceeded [] => IN-LIMITS aircraft=AIRWORTHY, unchecked.

The number two is still printed. It was computed correctly and consulted by nothing. Renaming the rule itself rather than the flag produced the same release with checked by library-builtin(accepts any due computation) on the line -- the word 'checked' surviving into an output where nothing was checked.

This is the pattern that has now appeared in every one of the last dozen areas: a quiet half switches off a loud half, and the pair is silent where each half alone was not. When a strict control sits behind an enabling flag and one pattern can reach both, the pair does not produce the loud outcome.

Losing the whole interval set is worse and reads better

With the entire interval configuration renamed, the engine examined zero criteria and reported every item IN-LIMITS. The operator's rule caught that too -- examined 0 of 3 -- but with the flag gone as well the run produced three lines reading examined 0 criterion(s) [] exceeded [] => IN-LIMITS aircraft=AIRWORTHY.

An item controlled by nothing is never overdue. An empty list of exceedances is indistinguishable from no exceedances, exactly as an empty list of unmet prerequisites is indistinguishable from a student who has met them all. Any check that reasons about what the engine found, rather than about what it should have looked at, agrees.

Why this particular guard survived being renamed

One arm in this area measured identical on both targets, and it is the most instructive result in the file. The declared criteria count -- the expectation the rule reads -- is written by the same bundle that reads it. Renaming moved the write and the read together, so the guard kept working.

That is worth stating plainly, because it cuts both ways. A value your own code writes and reads is invisible to a rename, which makes it robust; it is also the reason such a value is worthless as a provenance assertion. If the criteria count came from a fetched maintenance programme instead, the read would move alone, the count would be unreadable, and the rule would refuse -- loudly, which is also fine. Either arrangement is safe here. What is not safe is the flag in front of it.

The remaining fields behaved as every value field has: the item identifier refused before computation, and the last-done counters and the tolerance all failed closed or changed only the printed configuration.

If you protect a maintenance or airworthiness tracker

Assert the number of criteria you evaluated against the number the item declares, and do not put that assertion behind a switch. In this area that one assertion was the difference between three overdue inspections being caught and an aircraft being released with an inspection 18 hours past its limit.

Then make a criterion that cannot be read an error rather than a criterion that is skipped. An engine that silently narrows the question it is answering is the whole failure mode; an engine that refuses to answer a question it cannot ask in full is not.

Operators shipping this kind of software to customer sites usually cannot control the runtime, which is what makes the build-time configuration the place to fix it -- see our notes on protecting self-hosted applications for the delivery side of the same problem.

Frequently asked questions

Did obfuscation change any maintenance status on its own?

No. Twenty-five base comparisons across five presets matched the unprotected run exactly. Every result here required member renaming aimed at a name the installed tracking engine also reads.

What happens when one of three whichever-comes-first criteria is lost?

The remaining comparisons stay perfect and the item is judged against them alone. An inspection 18.4 hours past its 100-hour limit reads IN-LIMITS because the hours criterion was never evaluated, while the calendar and landing figures print correctly.

Did any check catch it?

Yes. A rule that refuses a status computed from fewer criteria than the item declares it is controlled by caught every one of the six routes measured -- the interval entry, the item's last-done counter, the airframe counter, the calendar entry, the landings entry and the whole interval set.

So the mitigation works?

It works when it runs. Renaming the enabling flag alongside the interval entry produced an airworthy aircraft with 'examined 2 criterion(s)' computed, printed, and consulted by nothing. Do not put a completeness assertion behind a switch that the same pattern can reach.

What does losing the whole interval configuration do?

The engine examines zero criteria and reports every item in limits. An item controlled by nothing is never overdue, and an empty list of exceedances looks exactly like a clean aircraft to any check that reasons about what was found.

Why did the guard's own expectation survive renaming?

Because it is written and read by the same bundle, so both moved together. That makes it robust against a rename and useless as evidence of provenance. A value fetched from another system would have failed closed instead, which is also safe.

What is the cheapest fix?

Compare the criteria you evaluated against the criteria the item declares, unconditionally, and treat an unreadable criterion as a refusal rather than a skip. Both are worth having regardless of obfuscation.

Related reading