# Tax engine — principles

## Purpose

This document anchors **how tax behaves** in the ERP relative to **operations** and **accounting**. Tax is an **interpretation and calculation layer** applied to documented economic events; it is **not** a second inventory or pricing engine and must **not** rewrite operational quantities or posted ledger history.

## Tax as a calculated layer

- **Operational documents** (orders, receipts, invoices, credit notes) carry **commercial facts**: quantities, unit prices, extensions, ship-to/bill-to, product references. They remain the **system of record** for physical and contractual state (see [posting-principles.md](./posting-principles.md)).
- **Tax determination** combines those facts with **tenant configuration** (tax codes, jurisdictions, effective dates, inclusive/exclusive rules—see [tax-model.md](./tax-model.md)) to produce **tax lines**: base, rate snapshot, tax amount, jurisdiction, and traceability keys.
- **Posted accounting** reflects tax through **journal entries** derived from agreed mappings ([tax-posting.md](./tax-posting.md)); the ledger does not “infer” tax from SKUs alone.

Calculations must be **pure functions** of: `(document snapshot, tax rules version, calculation policy version)` for a given line—no hidden globals (e.g., “current default rate” without versioning).

## Separation from operational quantities

- **Do not** change ordered or received **quantities** to satisfy tax rounding or cash-register conventions. Rounding belongs on **money and tax line** outputs (with explicit rounding mode per policy).
- **Do not** overwrite historical **unit prices** on operational lines when tax law or rate tables change; corrections flow through **new documents**, **adjustments**, or **new postings** with new effective snapshots.
- Operational **gross vs net** display may mirror tax-inclusive pricing for UX, but **persistence** of what was agreed commercially must remain distinct from **tax breakdown** rows stored for audit.

## Replay-safe calculations

**Replayability** means: given the same frozen inputs, any worker or batch reproduces **identical** tax lines and the same **posting payload** (subject only to declared floating-point or decimal policy).

Requirements:

1. **Version everything that affects math:** tax code definitions, rate schedules, jurisdiction graphs, rounding rules, and algorithm version (`tax_engine_version` or equivalent).
2. **Snapshot on document commit** (or on posting handoff): rates and rules **effective at that moment** are stored on the tax line or a sidecar snapshot—not “looked up live” at posting time without an explicit second snapshot for audit diff.
3. **Idempotent posting** (see [posting-principles.md](./posting-principles.md)): retries must not double tax in the ledger; correlation + idempotency keys tie tax postings to source lines.
4. **No mutation of historical truth:** posted tax journals and frozen document tax snapshots are **append-only**; law changes affect **new** periods and **new** entries, not silent edits to prior snapshots (see [journal-entry-model.md](./journal-entry-model.md)).

## Relationship to determinism

Tax and FX (see [multi-currency-model.md](./multi-currency-model.md)) are **accounting interpretations**. They must preserve the same hierarchy of values as core reporting: **Consistency > performance; auditability > shortcuts; determinism > implicit recalculation.**

## Self validation (this document)

- Tax positioned as a **calculated layer** over operational facts plus versioned rules.
- **Separation** from operational quantities and prices enforced.
- **Replay-safe** rules: version, snapshot, idempotency, no historical mutation.
