AWRA OpsHub Search

The Ceiling That Is Only on Two of Three Doors

A tax rate here cannot be created above one hundred per cent by any route. It can be updated above it through one. The rule was written on two doors out of three, which is the ordinary way a validation gap happens and the ordinary reason nobody notices.

Sales Insights AWRA OpsHub Team 11 min read

Validation feels like a property of a field. It is not. It is a property of each route that writes the field, and a system with three ways to write something has three chances to get it right and three chances not to.

The position, stated first

Two of the three paths that set a tenant tax rate cap it at one hundred. The third — updating an existing rate through the API — does not. Nothing downstream re-checks, so a rate above the ceiling would be applied to invoices as written. Found by audit, filed, and small to fix.

Three doors

A tenant maintains its own tax rates. There are three ways to write one: create it on the settings screen, create it through the API, or update an existing one through the API.

The first two require the rate to be a number, at least zero, and at most one hundred. The third requires a number and at least zero.

Path Minimum Maximum
Create, on the settings screen 0 100
Create, through the API 0 100
Update, through the API 0 none

Nobody wrote a rule allowing a rate above one hundred. Somebody wrote a rule three times and got it right twice, which is how almost every validation gap is made.

Why the ceiling is there at all

A percentage above one hundred is not automatically wrong — some duties genuinely exceed the value of the goods. So the ceiling is a judgement rather than a law, and it is a reasonable one for a general-purpose rate table where the overwhelming majority of realistic values sit below thirty.

What matters is not whether one hundred is the right number. It is that the system holds one opinion on two doors and a different one on the third, so the constraint is not a constraint — it is a suggestion that two routes happen to enforce.

What a typo costs

This is not an attack. It is a fat finger, through an integration, on a rate somebody meant to change from sixteen to seventeen and instead changed to seventeen hundred.

One digit, on an invoice of 10,000

Intended rate 17%
Rate as written 1700%
Would the create path allow it No
Would the update path allow it Yes
Would anything downstream refuse No
What catches it A person reading the invoice

Illustrative. The point is the last row: the only control on an absurd rate is that somebody notices the total, which is a control that works exactly as well as the person is having a good day.

The general shape

Wherever a system has grown a public interface alongside its screens, this pattern appears. The screen and the API create path are usually written together, because they are usually written when the feature is built. The update path is often added later, by somebody solving a different problem, copying the shape of the create rules and simplifying.

And it is invisible from every direction except one. The screen behaves correctly. The API create behaves correctly. Every test of both passes. Only a comparison of the three rule sets side by side shows it, and almost nothing prompts anybody to do that comparison.

  1. Enumerate the write paths for a field, not the field

    Screen, API create, API update, importer, and any background job. Five is common. The number is almost never one.

  2. Put the rules side by side

    Not read in sequence — literally beside each other. A difference is obvious in a table and invisible in two files.

  3. Ask which door was added last

    That is where the gap will be, in most systems, most of the time. It was here.

  4. Prefer one shared rule set to three matching ones

    Three rule sets that agree today are three rule sets that will disagree eventually. Agreement by construction beats agreement by discipline.

What we would build

The fix, and the thing that would stop it recurring

The first is a one-line correction. The second is the reason it happened and is worth more.

One rule set behind all three doors

A shared validation definition the screen, the API create and the API update all use, so the three cannot drift. This is a small refactor and it removes an entire class of defect rather than one instance of it.

A test that compares the doors

An automated check asserting that the create and update rules for a field agree, across every controller pair in the product. We already have checks shaped like this for permissions and for escaping; this is the same idea pointed at validation.

How it works: you describe the requirement, we return a written scope, timeline and cost, and once agreed it is built into your environment and maintained as part of the product. The second item above is the sort of thing we build for ourselves and then keep.

Talk to us about API validation

Four questions about validation, for any system with an API

How many ways can this field be written?

A good answer sounds like

A list, including the importer.

What it actually means

The count is the whole exposure, and almost nobody has it to hand.

Do the create and update rules match?

A good answer sounds like

Yes, and they share a definition.

What it actually means

"Yes" from memory is not evidence. Ours matched on two doors of three.

Does anything downstream re-check the value?

A good answer sounds like

For anything that moves money, yes.

What it actually means

Validation at the door is the only check in most systems, which makes the door the whole control.

Which write path was added most recently?

A good answer sounds like

They know.

What it actually means

That is where to look first, in any product, including this one.

Tax rate maintenance, precisely

What AWRA OpsHub does today

  • Tenant-maintained tax rates with jurisdiction, inclusivity, a default flag and effective dates.
  • A ceiling of one hundred per cent on both create paths, web and API.
  • A shipped rate preset per country, so a tenant starts from something rather than from nothing.
  • A provenance record behind the shipped presets, with a verified date, so freshness is visible rather than assumed.

What it does not do

  • A ceiling on the API update path, which is the finding on this page.
  • A single shared validation definition across the three write paths.
  • Any downstream sanity check on a rate before it is applied to a document.
  • Any warning when a rate changes by an implausible amount.
  • Fiscal transmission anywhere outside Kenya, so a rate here is used to compute and to print, not to file.

Not ours, by choice

  • This was found by auditing our own controllers while writing this batch, and it is recorded with its file and line references rather than quietly patched.
  • The effective-date fields on a tenant rate are dormant, which is a separate and already-published finding — this page is about the ceiling only.
  • Nothing here is American or Canadian, and no rate on this page is asserted as a real one anywhere. North America is here because sales tax varies by jurisdiction, so tenants maintain their own tables and the update path gets used.

Count the doors, then compare them

For any field that matters — a rate, a limit, a threshold — list every route that writes it and put the rules side by side. It is a ten-minute exercise and it is the only one that finds this.

Talk about data integrity

Frequently asked questions

Has this affected anybody?

It requires somebody to update a rate through the API to a value above one hundred, which is not something a normal integration would do. It is a hole rather than an incident, and it is being reported as one.

Why not just remove the ceiling everywhere?

That is a legitimate option, since a rate above one hundred is not inherently invalid. What is not legitimate is holding both opinions at once — either the ceiling is right and all three doors enforce it, or it is wrong and none of them do.

Does the API require authentication for this?

Yes, and permission. This is not an open endpoint; it is a hole reachable by somebody who is already entitled to change your tax rates, which is exactly the person a typo comes from.

Help Center

Need a quick answer while you read?

Run inventory, procurement, assets, sales, and field work with approved AWRA guidance for setup, migration, integrations, security, pricing, and support.

Search all approved AWRA public help articles.

Open Help Center