## Business Value
Finance's confirmed budgets are tax-inclusive, while every dollar Klair showed for Anthropic, OpenAI and Cursor was the vendor's pre-tax bill — so Budget-vs-Actuals, the BU dashboards and the weekly emails all understated actuals by 6.6% (8.25% sales tax on 80% of the bill) and every "under budget" readout was optimistic by exactly that margin. This came to a head in Ravi's recon thread (2026-08-13): the May Anthropic vendor PDF shows ≈ $876.7K, while Klair showed $822,206 — apply the uplift and 822,206 × 1.066 = $876,471, matching the PDF within ~$16. After this PR, displayed actuals for the three taxed vendors are directly comparable with the budgets Finance confirmed, ending a class of recurring reconciliation questions.
## Manual Effort Estimate
~12 hours focused (1.5 days): ~2h to map every dollar read-path across the live dashboard service, mart service and leaderboard email; ~3h to reason through the Anthropic allocation CTE + FR10 TrueFoundry day-factor interaction so the uplift applies exactly once; ~2h for the 14 direct-aggregate call sites + shared expressions; ~4h updating/extending the executable SQLite tie-out suites; ~1h verification. *Proposed by Claude — Keval to confirm/adjust.*
## What changed
One shared constant pair in services/ai_costs_service.py — SALES_TAX_MULTIPLIER = "1.066", TAXED_PROVIDERS = ("anthropic", "openai", "cursor") — reused everywhere; no duplicated literals.
services/ai_costs_service.py (live dashboard):
- Anthropic: the billed-dollar allocation CTE now allocates pre-tax in anthropic_allocated_pretax and the terminal anthropic_allocated CTE re-selects it with amount * 1.066. Every consumer (summary, time series, by-model, by-BU, top drivers, prior period) reads the uplifted terminal CTE unchanged.
- TF add-back (Anthropic): scales automatically — see Verification.
- OpenAI: all 7 direct aggregate sites over raw_openai_cost_reports multiply the summed output by the constant; the TF-OpenAI tf_billed_day day-factor numerator is uplifted once so the rescaled gateway add-back matches the uplifted direct slice.
- Cursor: all 7 aggregate sites over raw_cursor_usage_events likewise.
services/ai_costs_mart_service.py (Activity/People/API-Keys explorer): one shared UPLIFTED_MART_COST CASE expression (CASE WHEN s.provider IN ('anthropic','openai','cursor') THEN s.total_cost_dollars * 1.066 ELSE s.total_cost_dollars END) applied at every dollar read site — person CTE, person detail (daily/model/provider/keys/prior), stack rank, entity detail, sparklines, by-BU series.
services/ai_spend_rank/leaderboard.py (daily leaderboard email): the same shared CASE expression (imported from the mart service) in its three mart spend queries, so the email matches the dashboards.
ai_spend_budget_service.py: no change needed — verified by reading: it delegates its QTD actuals to AICostsService.get_by_bu (lines 474, 611–612, 873–895), so it inherits the uplift.
## What deliberately stays pre-tax
- Warehouse tables and DDL — raw_* staging tables, mart_saas_metrics.fct_ai_spend; the uplift lives only at the API read layer.
- v_ai_spend_anthropic_reconciled recon view — reconciliation against vendor invoices must stay pre-tax to tie out.
- Raw Data Reports drill-downs — get_anthropic_cost_reports*, get_anthropic_token_usage* (including reconciled_cost_dollars): these tie to the vendor's invoice rows verbatim.
- claude_ai / gcp / bedrock / azure / TrueFoundry gateway cash — not in TAXED_PROVIDERS; keyword-provider GL amounts are booked invoices, already tax-inclusive.
- Freshness/completeness SQL and the TF identity-resolution activity ranking (ordering heuristic; a constant multiplier cannot change an ordering it applies to uniformly).
## Verification
Test runs (all green):
- pytest tests/test_ai_costs_service.py tests/test_ai_costs_mart_service.py tests/test_ai_spend_budget_service.py tests/mart_saas_metrics/ tests/ai_spend_rank/ -q → 469 passed, 0 failed
- Adjacent AI-spend suites (test_ai_costs_anthropic_token_usage_service, test_ai_spend_bu_overrides_service, test_ai_costs_azure_token_usage_service, routers/test_ai_spend_budget_router, test_aws_spend_service) → the only 5 failures are byte-identical on origin/main (env-dependent email/AWS tests), verified by stash-swapping to the base commit.
- Full local pytest tests/ hits 60 collection errors from credential-requiring imports (zenpy/OpenAI keys) — verified identical on origin/main, unrelated to this change; CI is the authoritative full run.
- ruff format + ruff check clean; pyright on changed files reports only the two findings already present on origin/main.
New tests: terminal-CTE-applies-multiplier (structural, exactly once), mart CASE targets exactly the three providers (structural + executable SQLite proof: cursor row × 1.066, gcp row unchanged), claude_ai pass-through unchanged, raw drill-down stays pre-tax, TF-OpenAI billed-day uplift, leaderboard queries embed the shared CASE.
TF add-back scaling analysis (the FR10 question): this was the clean case — the Anthropic day factor is the ratio tf_billed_day / tf_computed_day where the numerator tf_billed_day sums TF-flagged rows from the uplifted terminal anthropic_allocated CTE, while the denominator is metered gateway cost. The factor therefore scales by exactly 1.066 and the add-back output (sum_cost_usd × factor) scales linearly with it — no double-apply, no gap; _tf_unmapped_billed (usage-less billed days → Unmapped) reads the same numerator and scales too. Total Anthropic = direct(non-TF) + TF add-back = billed_total × 1.066 exactly, proven by the executable SQLite tie-out test_day_factor_sql_rescale_ties_out_to_billed, which runs the unmodified production SQL and asserts direct + rescaled_TF == SUM(amount) == 190 × 1.066 with every term from executed SQL. The OpenAI TF add-back was the one asymmetric spot: its billed-day numerator reads the pre-tax raw table directly, so it gets the single explicit uplift noted above (proven by the two TF canonical-BU fold executable tests, factor 2 → 2 × 1.066).
Merge order: coordinate with #3534 / #3537 — this PR intentionally changes displayed totals by +6.6% for anthropic/openai/cursor, so anything asserting or screenshotting current totals should land relative to it deliberately.
🤖 Generated with [Claude Code](https://claude.com/claude-code)