# Regional tax rules for multi-state or VAT zones are enforced

- **Pattern:** `ab-001231` (`ecommerce-shipping-tax.regional-compliance.regional-tax-rules`)
- **Severity:** low
- **Lifecycle:** active
- **Last modified:** 2026-04-18
- **Canonical URL:** https://auditbuffet.com/patterns/ab-001231
- **License:** CC-BY-4.0 — attribute to AuditBuffet Pattern Catalog (https://auditbuffet.com/patterns/ab-001231)

## Why it matters

South Dakota v. Wayfair (2018) eliminated the physical presence requirement for sales tax nexus, meaning any US online seller that crosses state economic thresholds ($100K or 200 transactions annually in most states) must collect and remit destination-state tax. A tax lookup table with only 2 entries (CA and NY) while serving 15 states means the store collects nothing from 13 states where it may already be liable. The Streamlined Sales Tax Agreement creates uniform filing in 24 member states; the EU VAT Directive 2006/112/EC imposes separate VAT registration requirements. Fewer than 3 configured jurisdictions in a multi-state store is not a cosmetic gap — it is unreported tax liability.

## Severity rationale

Low severity in the audit context because manual remediation is required anyway, but the real-world tax liability exposure scales directly with the number of states served and the sales volume.

## Remediation

Expand the tax configuration in `lib/tax.ts` to cover at least all states where the business has economic nexus, or delegate entirely to a tax service API:

```ts
// lib/tax.ts
// Option 1: TaxJar handles nexus, Wayfair rules, and VAT automatically
const taxJarClient = new TaxJar({ apiKey: process.env.TAXJAR_API_KEY })
async function getTaxRate(address: Address): Promise<number> {
  const result = await taxJarClient.rates.get(address.zip, {
    state: address.state, country: address.country
  })
  return result.combined_rate
}

// Option 2: Local table — must include all nexus states
// Origin-based (sell from IL): use origin state rate
// Destination-based (most US states): use buyer's state rate
// Document which approach applies:
const TAX_BASIS: 'origin' | 'destination' = 'destination'
```

Add a code comment documenting the origin-vs-destination basis and the date the jurisdiction list was last reviewed.

## Detection

- **ID:** `regional-tax-rules`
- **Severity:** `low`
- **What to look for:** Count the number of distinct tax jurisdictions configured in the tax logic. Classify whether the tax system uses: (1) origin-based taxation, (2) destination-based taxation, or (3) a tax service API that handles jurisdiction rules. List which states or countries have explicit tax configurations.
- **Pass criteria:** The tax system explicitly handles at least 3 distinct jurisdictions with different tax rates, or delegates jurisdiction logic to a tax service API (TaxJar, Avalara, Stripe Tax). Origin-based vs. destination-based taxation is documented in a code comment or config.
- **Fail criteria:** Tax logic has fewer than 3 distinct jurisdiction configurations while the business claims to serve multiple states/countries, or no origin/destination tax distinction exists.
- **Skip (N/A) when:** The business operates in a single jurisdiction, or tax rules are fully managed by an external service (TaxJar, Avalara) with no in-house override logic.
- **Detail on fail:** `"Tax lookup table has 2 jurisdictions (CA: 7.25%, NY: 8%). Business serves 15 states — 13 states have no configured rate."` or `"No origin-based vs. destination-based distinction. All states use destination-based without documentation."`
- **Remediation:** Implement regional tax rules in `lib/tax.ts`:

  ```ts
  const ORIGIN_BASED_STATES = ['NY', 'IL', 'PA'] // states using origin-based

  function getTaxRate(address: Address, businessOrigin: Address): number {
    if (address.country !== 'US') {
      return getVATRate(address) // EU/international
    }

    if (ORIGIN_BASED_STATES.includes(businessOrigin.state)) {
      return getTaxRateByState(businessOrigin.state)
    } else {
      return getTaxRateByState(address.state) // destination-based
    }
  }
  ```

## External references

- external south-dakota-v-wayfair-2018 — https://www.supremecourt.gov/opinions/17pdf/17-494_j4el.pdf
- external streamlined-sales-tax-agreement — https://www.streamlinedsalestax.org/for-businesses/overview
- external eu-vat-directive-2006-112-ec — https://eur-lex.europa.eu/legal-content/EN/TXT/?uri=CELEX%3A32006L0112

Taxons: regulatory-conformance, data-integrity

HTML version: https://auditbuffet.com/patterns/ab-001231
