Measured Behaviour

Does obfuscation break indirect cost recovery?

Every sponsor asks what your indirect rate is. Nobody asks what your base is. The rate is one number on the face of one agreement and it cannot move quietly. The base is not a number at all - it is a set membership rule spread across three separate options - and we measured what happens when a rename reaches each of them.

A rate is a number times a set, and only the number is audited

We built a budget year the way a real one is shaped: thirty-six ledger lines across nine categories, a negotiated rate of 54.5 per cent on a modified total direct cost base, four categories carved out of that base by the agreement (equipment, tuition, participant support and rent), subawards in the base only to the first 25,000 dollars each, cost-shared lines carrying no overhead, a period of performance that closes on day 365, and an award ceiling of 168,000 dollars on what may be recovered.

The correct run reports direct costs of 1,046,900.00, a base of 316,100.00 after the carve-outs, a computed recovery of 172,274.50, and an invoiced recovery of 168,000.00 because the ceiling binds. Total to the sponsor: 1,214,900.00. The institution's own agreement check - recovery must not exceed the negotiated rate applied to the agreed base - passes.

We then protected the file with default settings on five profiles: the ES5 target, the modern target, both emit-gate configurations and the string-encoding profile. All five produced identical behaviour. That is the first result and it deserves stating plainly - protection on its own did not move a dollar of the base or a cent of the invoice.

The failures start when member renaming is pointed at the names on the agreement object, which is what a regexp like ^(excludedFromBase)$ or a broad RenameMembers pattern over a configuration literal actually does. If you have not yet decided how far your member pattern reaches, the mechanics are documented in Protect Members.

The carve-out list doubled the base and changed the invoice by nothing

The four excluded categories exist for a reason that is easy to state: an institution does not incur administrative overhead in proportion to the price of a microscope, a student's tuition, a stipend paid straight through to a participant, or rent it passes on at cost. Take the list away and all four re-enter the base.

Measured: the base went from 316,100.00 to 738,500.00 and the computed recovery from 172,274.50 to 402,482.50. Equipment carried 242,100.00 of base it is specifically excluded from carrying, rent 95,700.00, participant support 58,500.00 and tuition 26,100.00.

And the invoice did not move. Invoiced recovery stayed 168,000.00 and the total to the sponsor stayed 1,214,900.00, identical to the cent, because the award ceiling was already binding and went on binding. Direct costs were unchanged. The rate printed on the invoice was still 54.5 per cent. The institution's own agreement check still passed, reporting 168,000.00 recovered within 402,482.50 permitted.

This is the arm a reviewer closes. Nothing billed changed, so on any reconciliation of what was invoiced against what was paid, there is nothing to find. The base is not on that reconciliation.

Two more options define the same base, and both are equally invisible

The carve-out list is one of three names that decide what the rate multiplies. We renamed the other two independently.

Renaming the base KIND - the single string that says modified total direct cost rather than total direct cost - took the base to 884,100.00 and the computed recovery to 481,834.50, nearly three times the correct figure. Invoiced recovery: 168,000.00, unchanged.

Renaming the per-subaward cap took the base to 461,700.00 and the computed recovery to 251,626.50, because the whole of every subaward entered the base instead of the first 25,000 dollars of each. Invoiced recovery: 168,000.00, unchanged.

So all three options that define the base are individually invisible on the invoice. A ceiling is a genuine control and it did genuine work here - but what it bought was silence, not safety, because it hid three separate ways the base had already gone wrong.

The ceiling is the fourth name, and the pair is the outage

Renaming the ceiling on its own is the least alarming arm in the file. Invoiced recovery went from 168,000.00 to 172,274.50 and the total to the sponsor from 1,214,900.00 to 1,219,174.50. The institution recovered 4,274.50 more - which is, in fact, what its negotiated rate applied to its agreed base entitles it to. It is hard to call that a defect at all.

Rename the ceiling and the carve-out list together and the picture changes completely. Invoiced recovery went to 402,482.50 and the total to the sponsor to 1,449,382.50 - 234,482.50 dollars of additional overhead billed to a federal award, charged on equipment, tuition, participant support and rent.

Neither half predicts the pair. One half moves nothing on the invoice and the other moves 4,274.50, and together they move 234,482.50. A member pattern narrow enough to catch only one of them looks clean; a pattern wide enough to catch both looks the same on every configuration screen you have.

The one arm you can see is the one that costs you money

There is exactly one option in this file whose loss is visible on the face of the invoice, and it is the rate. Renaming indirectRatePct reverts 54.5 per cent to the federal de minimis rate of 10 per cent, which is what an entity with no negotiated agreement may charge. Invoiced recovery went from 168,000.00 to 31,610.00.

That arm is loud in the only place anybody looks. The invoice now says 10 per cent. Somebody will notice, because the number is wrong in the direction that reduces the institution's income by 136,390.00 and because a rate is the one figure a sponsored programmes office checks by reflex.

Put the two together and the shape of the risk is uncomfortable. The half of the calculation that fails visibly fails in your own disfavour and self-corrects, because somebody chases the missing money. The half that fails invisibly fails in the sponsor's disfavour and does not self-correct, because over-recovery is not a number anybody in the institution is looking for.

For teams shipping federal-facing build tooling, the surrounding control expectations are set out in FedRAMP, CMMC and Your JavaScript Build.

What to do about it

None of this is an argument against protecting the code. The engine's default profiles moved nothing at all in this file - the damage came entirely from a member-renaming pattern reaching a configuration object, and that pattern is something you choose.

Keep the configuration literal out of the member pattern. A rate agreement object is not where obfuscation earns anything: an attacker who reads your F and A rate has learned a number that is published on your institution's website. Point the pattern at the logic you actually want to protect and exclude the settings object by name.

Assert the base, not just the rate. The correct run above prints its base and its base by category. A single test that pins the base to 316,100.00 would have failed on every one of the three silent arms, and no test that pins only the rate would have failed on any of them.

And treat a ceiling as an amplifier of silence rather than a safety net. It capped the damage in one arm and hid three different defects while doing it.

Frequently asked questions

Did obfuscation change the indirect cost calculation on its own?

No. On all five profiles we tried - the ES5 target, the modern target, both emit-gate configurations and the string-encoding profile - the protected bundle produced identical behaviour to the original. Every difference in this article came from member renaming reaching the names on a configuration object, which is a pattern you choose rather than a default.

Why did more than doubling the base not change the invoice?

Because the award carried a recovery ceiling of 168,000.00 dollars that was already binding. The computed recovery went from 172,274.50 to 402,482.50, but the invoiced figure is the lesser of the computed recovery and the ceiling, so it stayed 168,000.00 and the total to the sponsor stayed 1,214,900.00.

Which single rename cost the sponsor the most?

None of them alone. The largest single-name move on the invoice was 4,274.50 dollars, from renaming the ceiling. Renaming the ceiling and the base carve-out list together billed 402,482.50 instead of 168,000.00, which is 234,482.50 dollars of additional overhead.

Does the negotiated rate itself ever look wrong?

Only in the arm where the rate option is the one renamed. There it reverts to the 10 per cent de minimis rate and the invoice prints 10 per cent, so it is visible immediately. In every other arm the invoice prints the correct 54.5 per cent while the base underneath it is wrong.

Would our own compliance check have caught this?

The check we modelled is the one institutions really write: recovery must not exceed the negotiated rate applied to the agreed base. It passed in every arm, because it recomputes rate times base from the same base the engine just computed. A rule cannot audit the input it is handed.

What should we pin in a test?

The base and the base by category, not just the rate and the total. Pinning the base to 316,100.00 fails on all three of the silent arms here. Pinning only the rate or only the invoiced total fails on none of them.

How do we stop member renaming from reaching the rate agreement?

Scope the member pattern so the configuration literal is excluded, and keep the pattern pointed at the code you actually want to make harder to read. The option and regexp mechanics are documented in Protect Members.

Related reading