Measured, not asserted

Does obfuscation break weight and balance calculations?

A load sheet has two numbers per item and only one of them is checked by anybody. The weight is added up and printed at the top of the sheet. The arm -- how far behind the datum the item sits -- is looked up, multiplied, and never seen again. This test renamed one entry in that lookup table and watched an aeroplane loaded behind its aft limit be released for flight with a gross weight that was exactly correct.

A load sheet is a weighted mean, not a sum

The gross weight of a loaded aeroplane is a sum, and sums are forgiving. Every item contributes its weight, the total is printed at the top of the sheet, and if an item goes missing the number visibly changes. The centre of gravity is not a sum. It is a weighted mean: each item's weight is multiplied by its arm -- the distance from the datum to the station it occupies -- the moments are added, and the total is divided by the weight.

That means each item enters the calculation twice, through two different routes. Its weight comes from the item itself. Its arm comes from a table, keyed by the name of the station. Lose the weight and the mean stops being finite, which is loud. Lose the arm and the item keeps its full weight in the divisor while contributing nothing to the dividend, so the computed centre of gravity slides toward the datum and the gross weight does not move at all.

The test fixture is a light twin at 9,150 lb gross with an envelope of 82.0 to 94.6 inches. Two departures carry the same total load in different places. The first is loaded forward and sits at 89.14 inches, comfortably inside. The second moves three passengers to the last row and the bags to the aft compartment, which puts it at 95.21 inches -- six tenths of an inch behind the aft limit -- and it must be refused until the load is moved.

Protection on its own moved nothing

Before any renaming, all five areas of this pass were run through five presets: the ES5 default path, the modern target, the emit gate's own option set on both targets, and the string transforms. Twenty-five comparisons, every one identical to the unprotected run, including the reproducibility guard that runs each original twice before anything is compared to it.

So nothing below is caused by protection as such. Every result in this article required member renaming pointed at a property name that both the load-sheet code and the installed balance engine read -- the failure mode this whole series exists to map.

One station key, and an out-of-limits aeroplane was released

The narrowest pattern measured in this area renamed a single entry inside the station table: the aft baggage compartment. Nothing else in the file was touched. The lookup for that station stopped matching, the engine substituted its standard arm of zero, and the aft bags were treated as sitting exactly on the datum.

The flight that was 0.6 inches out of limits was RELEASED, at a computed 89.18 inches. The gross weight printed 9,150 lb, correct to the pound. The envelope printed 82.0 to 94.6, correct. The operator's own load-sheet check ran, passed, and reported four items placed. And the configuration dump printed the station table as row1:85 row2:118 row3:141 _0x1:178 fwdbag:40 -- the arm is still there, still 178 inches, listed under a name the lookup no longer asks for.

That last detail is the one worth carrying away. A populated configuration screen is evidence that entries exist. It is never evidence that anything finds them.

The placement line even printed aftbag@0, which is the arm the calculation actually consumed. Printing the value a guard consumed is a real improvement over printing only its conclusion, and here it was not enough, because zero is a legitimate arm. It is the datum. A number that means 'we could not find this station' and a number that means 'this station is at the reference point' are the same number.

The wider pattern was the safer one

Renaming the whole station table -- the option key rather than one entry inside it -- produced the opposite result. Every station fell back to the standard arm, the centre of gravity collapsed to 78.26 inches for both flights, and both were REFUSED as forward of the 82-inch limit. Loud, immediate, and impossible to miss on the first departure of the day.

Renaming the station field on the load items themselves did the same thing, and printed placed[undefined@0 undefined@0 undefined@0] on the way past.

So the broad, obvious pattern fails closed and the narrow, careful one flies an aeroplane out of limits. That is not a quirk of this fixture. It is the third time in this pass alone that testing only the widest pattern would have hidden the dangerous cell, and it is the reason a rename policy has to be tested one name at a time rather than only as the union everybody actually ships.

The envelope itself is an option, and its default has no opinion

The aft limit is not a record field. It is a configuration key, and a configuration key never becomes unreadable: the library simply substitutes its own default. This engine's default aft limit is positive infinity, because a general-purpose balance library cannot know the airframe.

With the aft limit renamed, the out-of-limits departure was released at 95.21 inches -- the correct centre of gravity, printed accurately, compared against an envelope reading 82.0..Infinity. Every input was right and the comparison had nothing to fail. The forward limit and the maximum takeoff weight behaved the same way, and only changed the printed configuration, because neither was binding on these two flights.

What failed loudly, and why that is not reassurance

Every value field in the area failed closed and said so. Renaming the item weight, the basic empty weight or the empty arm produced non-finite-empty-weight(refused before computation) or non-finite-item-weight. Renaming the tail number produced unidentified-aircraft. Renaming the ok field on the caller's own guard turned every release into sheet-rejected, which grounds the fleet and gets fixed the same morning.

The pattern is now twelve areas old and it held again here: losing a VALUE fails closed and loud, losing a MEANING -- an arm, a unit, a scope, a row -- fails open and silent. The loud half is the one people find in testing. The silent half is the one that ships.

If you protect a load-planning application

Three things came out of this area that are worth having whether or not you obfuscate anything, because a hand-edited configuration file, a dropped key over a serialisation hop and a library upgrade all produce the same miss.

First, make an unresolved station an error rather than a default arm. An engine that cannot find a station should refuse to compute, not quietly place the item at the datum. Second, reconcile the moment as well as the weight: a load sheet whose gross weight is right and whose moment total is wrong is exactly the artefact this test produced, and the moment is the number nobody prints. Third, keep the names your protected build shares with an installed engine out of the rename pattern entirely -- a member regexp that names the fields you own is a five-minute edit and it removes the whole class.

If you are protecting operational software of this kind, the practical route is a narrow member pattern plus a build that is verified by executing the artefact, not by reading the diff. Our security evidence pack covers what to keep from a build so an auditor can see which names moved.

Frequently asked questions

Did obfuscation change any weight and balance result on its own?

No. Five areas were run through five presets and every protected output matched the unprotected run -- twenty-five comparisons, no differences. Every failure in this article required member renaming aimed at a property name the installed balance engine also reads.

What exactly went wrong when a single station key was renamed?

The lookup for that station stopped matching, so the engine used its standard arm of zero. The aft bags were treated as sitting on the datum, the centre of gravity moved from 95.21 to 89.18 inches, and a departure that was six tenths of an inch behind the aft limit was released.

Was the gross weight wrong?

No, and that is the point. The gross weight was 9,150 lb before and after, correct to the pound, because an item that loses its arm keeps its weight. Only the weighted mean moved. A load sheet reconciliation that checks the total weight cannot see this.

Why was renaming the whole station table safer than renaming one entry?

Losing the whole table sent every station to the standard arm, which collapsed the centre of gravity to 78.26 inches and refused both departures as forward of the limit. The failure was total, immediate and visible. Losing one entry moved one aeroplane a few inches and left everything else correct.

Does printing the arm that was used protect you?

Only partly. The test printed aftbag@0 on the placement line, which is the arm the calculation consumed. Zero is also the datum, so a reader cannot distinguish 'station not found' from 'station at the reference point' without knowing the table. Print the arm and the station it came from, or refuse.

Which fields failed loudly?

Item weight, basic empty weight, empty arm and tail number all refused before computation with non-finite or unidentified messages, and renaming the guard's own ok field rejected every load sheet. Values fail closed; the meanings attached to them fail open.

What is the cheapest fix?

Make an unresolved station an error rather than a default arm, and reconcile the total moment as well as the total weight. Both are worth doing regardless of obfuscation, because a dropped key in a configuration file produces exactly the same result.

Related reading