DEV Community

Cover image for How VAT Calculation Provenance Makes Results Explainable
Vasyl Kyryliuk for VAT Engine

Posted on Originally published at vat-engine.app

How VAT Calculation Provenance Makes Results Explainable

A VAT calculation can be numerically correct and still be difficult to trust.

Imagine an API returns:

{
  "net_amount_minor": 10000,
  "vat_amount_minor": 1900,
  "gross_amount_minor": 11900,
  "vat_rate_bps": 1900
}
Enter fullscreen mode Exit fullscreen mode

The arithmetic looks straightforward.

But if someone reviews that result six months later, they may ask:

  • Where did the 19% rate come from?
  • Which rate dataset was used?
  • Which mapping participated in the decision?
  • Which version of the calculator produced the amounts?
  • What evidence was actually captured?
  • Can the original result be reproduced exactly?
  • Has the underlying rate data changed since then?

The final number alone cannot answer those questions.

That is what calculation provenance is for.

Provenance connects a financial result to the data, versions, mappings, and calculation contract that produced it.

For a VAT API, that can make the difference between:

VAT = €19.00
Enter fullscreen mode Exit fullscreen mode

and:

VAT = €19.00
because this rate evidence, mapping context, date, and calculation contract produced it
Enter fullscreen mode Exit fullscreen mode

The second result is much easier to explain.

A result and its provenance are different things

The result tells you what was calculated.

Provenance helps explain how the system arrived there.

A VAT result might contain:

{
  "vat_rate_bps": 1900,
  "net_amount_minor": 10000,
  "vat_amount_minor": 1900,
  "gross_amount_minor": 11900
}
Enter fullscreen mode Exit fullscreen mode

Its provenance can describe things such as:

rate source
rate data version
mapping version
effective date
calculation version
evidence status
source references
replay status
Enter fullscreen mode Exit fullscreen mode

These serve different purposes.

The calculation output is useful for checkout, invoices, reporting, and reconciliation.

The provenance becomes useful when someone needs to understand or review the result later.

Why the percentage alone is not enough

Consider two calculations that both use:

19%
Enter fullscreen mode Exit fullscreen mode

They may look identical numerically.

But they could have been selected through completely different evidence paths.

For example:

Calculation A:
country = DE
tax class = standard
reviewed rate evidence = A

Calculation B:
country = DE
tax class = standard
legacy recorded window = B
Enter fullscreen mode Exit fullscreen mode

Both might produce:

1900 basis points
Enter fullscreen mode Exit fullscreen mode

That does not mean they have the same provenance.

A matching percentage does not prove:

  • the same source was used,
  • the same historical applicability was established,
  • the same mapping was used,
  • or the same evidence quality existed.

Numeric equality is not provenance.

Start with rate provenance

VAT Engine separates the numeric VAT rate from the evidence describing where that rate came from.

A response can include a structure such as:

{
  "rate_provenance": {
    "schema_version": "rate-evidence/v1",
    "evidence_status": "legacy_unverifiable",
    "source": "legacy_recorded_window",
    "effective_at": "2026-01-28T00:00:00Z",
    "source_evidence": []
  }
}
Enter fullscreen mode Exit fullscreen mode

The important part is not the exact JSON shape.

It is that the API does not pretend:

rate = 19%
Enter fullscreen mode Exit fullscreen mode

is the complete explanation.

Instead, the result can carry information about the evidence state behind that rate.

Evidence status should be explicit

A common design mistake is to reduce evidence to:

{
  "verified": true
}
Enter fullscreen mode Exit fullscreen mode

That usually hides too much.

Historical and financial data often has more than two meaningful states.

For rate evidence, VAT Engine distinguishes states such as:

verified
legacy_unverifiable
unavailable
Enter fullscreen mode Exit fullscreen mode

These communicate different things.

verified

The required reviewed rate evidence is available for that recorded path.

legacy_unverifiable

The historical record exists, but the evidence needed to prove it to the current standard was not captured.

unavailable

The required evidence cannot currently be established.

This is more informative than silently converting uncertainty into certainty.

Legacy records should stay legacy

Suppose an old VAT calculation used a recorded rate of:

19%
Enter fullscreen mode Exit fullscreen mode

Later, a reviewed source also contains:

19%
Enter fullscreen mode Exit fullscreen mode

It can be tempting to mark the old record as verified.

But the old record may not contain:

  • the original reviewed source version,
  • source-supported applicability evidence,
  • the original mapping digest,
  • or the source references needed by the newer evidence model.

So the safer rule is:

Do not retroactively upgrade provenance merely because the numbers match.

VAT Engine keeps that distinction explicit.

Older records can remain:

legacy_unverifiable
Enter fullscreen mode Exit fullscreen mode

instead of being assigned stronger provenance by inference.

That preserves what the system actually knows.

Historical rate windows need careful interpretation

This matters especially for historical VAT data.

A recorded lookup window may describe:

when the system observed or applied a rate
Enter fullscreen mode Exit fullscreen mode

while legal applicability asks:

when the rate was actually applicable according to the authoritative source
Enter fullscreen mode Exit fullscreen mode

Those are not automatically the same thing.

Older imported or live-recorded windows can reflect observation or application time.

Where approved source-supported coverage exists, the evidence can be stronger.

But a legacy recorded window should not suddenly be described as a legally verified applicability interval.

That distinction is part of provenance.

I covered this temporal boundary in more detail here:

Current VAT Rate vs Transaction-Date VAT Rate: Why the Difference Matters

Mapping provenance matters too

A VAT rate is usually not selected from country alone.

The system may need to resolve something like:

product or classification context
→ mapping
→ tax treatment
→ rate
Enter fullscreen mode Exit fullscreen mode

Mappings can change over time.

If a mapping changes in July, the current mapping does not necessarily explain why a January calculation produced its result.

That is why a calculation record can benefit from preserving mapping identity.

VAT Engine can retain fields such as:

mapping_version
mapping digest
Enter fullscreen mode Exit fullscreen mode

alongside rate evidence.

This lets a later review distinguish:

the mapping used then
Enter fullscreen mode Exit fullscreen mode

from:

the mapping configured now
Enter fullscreen mode Exit fullscreen mode

Calculation provenance is separate from rate provenance

Even if the selected rate is fully understood, the arithmetic still has its own provenance.

A financial calculation can depend on:

  • rounding rules,
  • inclusive vs exclusive pricing,
  • currency scale,
  • validation behavior,
  • calculator version.

VAT Engine therefore exposes calculation provenance separately.

For example:

{
  "calculation_provenance": {
    "schema_version": "calculation-evidence/v1",
    "calculation_version": "vat-calculator-half-up/v1",
    "execution_digest": "...",
    "algorithm_manifest_version": "vat-algorithm-manifest/v1",
    "algorithm_manifest_digest": "...",
    "ownership": "tenant_owned",
    "evidence_status": "captured",
    "replay_status": "ineligible"
  }
}
Enter fullscreen mode Exit fullscreen mode

This answers a different question:

Which registered calculation contract produced these amounts?

That remains useful even if the VAT rate itself has not changed.

Why calculator versions matter

Financial software evolves.

Imagine that a later calculator version changes:

rounding behavior
currency-scale handling
validation rules
Enter fullscreen mode Exit fullscreen mode

If an old transaction is reviewed after that change, running today's code may not be enough to explain yesterday's result.

Without calculation provenance, the investigation becomes:

Why does the API behave differently now?
Enter fullscreen mode Exit fullscreen mode

With provenance, the question becomes:

Which calculation contract produced the original result?
Enter fullscreen mode Exit fullscreen mode

That is much more precise.

An execution digest is not a source-code hash

Technical provenance should also be described carefully.

VAT Engine exposes an:

execution_digest
Enter fullscreen mode Exit fullscreen mode

That is not presented as:

a hash of the compiled binary
Enter fullscreen mode Exit fullscreen mode

or:

cryptographic proof of every runtime instruction
Enter fullscreen mode Exit fullscreen mode

It identifies the registered calculation-version contract.

VAT Engine can also retain an algorithm manifest version and digest that bind the defined arithmetic, validation, currency-scale, rounding, and frozen-fixture contract.

That gives the result a stable technical identity without claiming more than the evidence actually proves.

Provenance should survive software updates

Your software will change.

Your rate imports will change.

Your mappings may change.

Your validation rules may change.

A historical calculation should not require today's mutable configuration to explain yesterday's result.

Instead, the record should preserve enough information to say:

this result came from this request
using this rate evidence
using this mapping context
using this calculation contract
Enter fullscreen mode Exit fullscreen mode

That makes historical behavior less dependent on current state.

Provenance improves debugging

Imagine a customer reports:

Your API charged 19% VAT, but I expected 7%.

Without provenance, the investigation might require reconstructing:

  • which rate data was active,
  • which tax class or mapping was selected,
  • which transaction date was used,
  • which calculator behavior was running.

With provenance, much of that context can already be attached to the calculation record.

A review becomes more structured:

1. Retrieve the calculation.
2. Inspect the transaction date.
3. Inspect the selected tax context.
4. Inspect the rate evidence.
5. Inspect the mapping version.
6. Inspect the calculator version.
7. Compare the recorded assumptions with the expected business facts.
Enter fullscreen mode Exit fullscreen mode

This does not automatically prove that the tax treatment was legally correct.

It does make the technical decision much easier to explain.

Provenance improves reconciliation too

Reconciliation often means comparing two systems.

For example:

VAT Engine
vs
Shopify

VAT Engine
vs
a billing platform

VAT Engine
vs
an accounting export
Enter fullscreen mode Exit fullscreen mode

If both systems show:

VAT = €19.00
Enter fullscreen mode Exit fullscreen mode

there may be nothing to investigate.

But if one says:

€19.00
Enter fullscreen mode Exit fullscreen mode

and the other says:

€7.00
Enter fullscreen mode Exit fullscreen mode

the useful question is not just:

Which number is correct?

You also need to know:

Which assumptions produced each number?

That may include:

  • jurisdiction,
  • product classification,
  • transaction date,
  • rate source,
  • amount basis,
  • rounding behavior.

Provenance turns reconciliation from a number comparison into a decision comparison.

Source references make evidence inspectable

A useful provenance model can include bounded references to the evidence behind a decision.

For reviewed rate paths, this can include public-safe references associated with:

rate versions
source snapshots
rate rows
mapping evidence
Enter fullscreen mode Exit fullscreen mode

The public response does not need to expose every internal database object.

It needs enough stable, safe references to explain what the system relied on.

This keeps the API useful without leaking internal implementation details.

Provenance is not the same as logging

Logging and provenance overlap, but they are not interchangeable.

A log might say:

2026-01-28 10:03:12 calculated VAT for DE
Enter fullscreen mode Exit fullscreen mode

That is operational telemetry.

Provenance belongs to the calculation record itself.

It answers questions such as:

Which rate source?
Which version?
Which mapping?
Which calculator?
Which evidence status?
Enter fullscreen mode Exit fullscreen mode

Logs can be rotated.

Trace IDs can disappear.

Infrastructure can change.

The stored calculation should still retain the information needed to explain its own result.

Provenance is not a committed sale either

Another boundary matters.

A calculation with useful provenance is still a calculation.

It does not automatically mean:

a sale happened
Enter fullscreen mode Exit fullscreen mode

or:

this record is a committed accounting event
Enter fullscreen mode Exit fullscreen mode

VAT Engine's Transactions API exposes VAT calculation history and evidence.

Calling:

POST /v1/vat/calculate
Enter fullscreen mode Exit fullscreen mode

records calculation history, but does not by itself add a sale to:

  • OSS threshold monitoring,
  • Filing Prep,
  • OSS/IOSS reporting.

Those workflows use committed supply data.

Calculation provenance explains the API calculation.

It does not manufacture a business event.

Provenance and replay are related, but not identical

Another useful distinction is between:

evidence captured
Enter fullscreen mode Exit fullscreen mode

and:

exactly replayable
Enter fullscreen mode Exit fullscreen mode

A calculation may retain useful evidence without retaining everything required for exact replay.

VAT Engine exposes that boundary through:

replay_status
Enter fullscreen mode Exit fullscreen mode

Possible states include:

not_supported
ineligible
available
Enter fullscreen mode Exit fullscreen mode

Only calculations reporting:

replay_status: available
Enter fullscreen mode Exit fullscreen mode

can use the exact replay endpoint.

That prevents the API from claiming reproducibility where the required sealed evidence does not exist.

Exact replay makes provenance testable

For eligible calculations:

POST /v1/transactions/{id}/replay
Enter fullscreen mode Exit fullscreen mode

uses the recorded:

original canonical request
+ sealed historical rate evidence
+ registered calculator version
Enter fullscreen mode Exit fullscreen mode

A successful replay returns:

exact_match: true
Enter fullscreen mode Exit fullscreen mode

with the reproduced amounts.

This makes provenance stronger than descriptive metadata alone.

The system can test whether the recorded evidence reproduces the stored result.

But replay still has strict boundaries.

The caller cannot choose:

another rate-data version
another calculator version
Enter fullscreen mode Exit fullscreen mode

because that would describe a different calculation, not a replay of the original one.

A useful provenance record answers several layers of "why"

When someone asks:

Why is the VAT €19?

there are several possible meanings.

Arithmetic

Why is €19 the mathematical VAT amount?
Enter fullscreen mode Exit fullscreen mode

Answer:

because €100 net at 19% produces €19 VAT
Enter fullscreen mode Exit fullscreen mode

Rate selection

Why was 19% selected?
Enter fullscreen mode Exit fullscreen mode

Answer:

because this recorded rate evidence was selected for this context and date
Enter fullscreen mode Exit fullscreen mode

Mapping

Why did this product or classification use that treatment?
Enter fullscreen mode Exit fullscreen mode

Answer:

because this recorded mapping context participated in the decision
Enter fullscreen mode Exit fullscreen mode

Reproducibility

Can we reproduce the original result?
Enter fullscreen mode Exit fullscreen mode

Answer:

only when the required sealed evidence exists and replay_status is available
Enter fullscreen mode Exit fullscreen mode

A single vat_rate field cannot answer all of those questions.

Provenance gives each one a place in the model.

What I would preserve in a provenance-aware VAT API

At minimum, I would separate the result from the evidence explaining it.

A useful structure might preserve:

Calculation identity

Input context:
- country / jurisdiction
- currency
- amount basis
- tax classification
- transaction date

Result:
- net amount
- VAT amount
- gross amount
- selected VAT rate

Rate provenance:
- evidence status
- rate source
- rate data version
- effective date
- rate-row identity
- source references where available

Mapping provenance:
- mapping version
- mapping digest or stable identity

Calculation provenance:
- calculation version
- execution identity
- algorithm manifest identity
- calculation evidence state

Reproducibility:
- replay status
Enter fullscreen mode Exit fullscreen mode

Not every financial API needs exactly these field names.

The architectural point is the separation.

What provenance should not do

Provenance is useful because it describes what the system actually knows.

It should not silently invent stronger claims.

Avoid patterns such as:

Upgrading old history because the number matches

old rate = 19%
reviewed rate = 19%

therefore old history is verified
Enter fullscreen mode Exit fullscreen mode

That does not follow.

Treating a recorded window as automatic legal applicability

Recorded/imported windows can reflect system history rather than authoritative legal dates.

Calling evidence capture exact replay

Evidence can be useful without being complete enough for replay.

Treating calculation history as a committed sale

A calculator call does not prove that a business transaction occurred.

Hiding uncertainty

legacy_unverifiable is more informative than pretending old evidence is equivalent to newly reviewed evidence.

Explainability is mostly about preserving context

A financial API does not become explainable because it adds a field called:

reason
Enter fullscreen mode Exit fullscreen mode

Explainability comes from preserving the actual chain of context behind the result.

For VAT, that can look like:

business input
→ classification or mapping
→ rate evidence
→ calculation contract
→ result
Enter fullscreen mode Exit fullscreen mode

If those links survive, the result remains understandable even after the software changes.

If they disappear, a historical VAT amount becomes just another unexplained number in a database.

The goal is not to store everything

There is a balance.

A provenance-aware API should not dump:

every SQL row
every internal log
every deployment detail
every implementation object
Enter fullscreen mode Exit fullscreen mode

into every response.

The goal is to preserve the identities and evidence boundaries that matter.

That usually means:

  • stable versions,
  • digests or identifiers,
  • evidence states,
  • bounded public references,
  • and enough context to reproduce or review the decision.

Good provenance is not maximum data.

It is the right data.

A financial result should be able to explain itself

The most useful way to think about provenance is this:

A stored calculation should carry enough context that a future version of your system can still explain why the result exists.

For VAT, that means going beyond:

19%
Enter fullscreen mode Exit fullscreen mode

and preserving:

where the rate came from
which mapping participated
which calculation contract ran
what evidence was available
whether the result can be replayed
Enter fullscreen mode Exit fullscreen mode

That does not turn an API into a tax authority.

It does make the API's own decisions easier to inspect, debug, reconcile, and reproduce.

For financial software, that is a meaningful improvement over returning the right number and forgetting how you got there.


You can inspect the current VAT Engine calculation contract here:

Calculate VAT API

The stored evidence and replay model:

Transactions API

And the historical-rate evidence boundary:

VAT Rates API

VAT Engine is currently in active alpha development. Evidence strength varies by record and source coverage; older records can remain legacy_unverifiable, and provenance does not by itself establish legal or tax correctness. VAT Engine does not provide tax or legal advice.

Top comments (0)