The FTC settled with Instacart for $60 million over pricing experiments that showed different shoppers different prices for identical items, up to 23% apart (FTC, December 2025). The FTC's case rested on the prices the experiments actually produced, with no finding of group-based discrimination attached to it. New York, Colorado and the EU have each put obligations on the books that reach algorithmic pricing, and the most common defence in AI pricing compliance, that the model has no protected attribute in its feature list, is worth less than the teams relying on it believe.
A revenue-optimizing contextual bandit will find every signal that predicts willingness to pay, including the ones that are really predicting who the shopper is. ZIP code predicts income. An old Android phone predicts less comparison shopping. Both of those signals track the protected class in this population, and on the synthetic engine in this demo a high-income-ZIP, new-device cohort and a majority-minority-ZIP, old-device cohort were priced 26.2% apart on the same $79.00 earbuds, the whole proxy-driven gap, membership skew included. We built Equity, a pricing-defensibility audit layer that sits on top of whatever pricing engine a retailer already runs, to put that leakage into numbers a General Counsel can defend, and to show what a defensible answer to a Civil Investigative Demand looks like once it arrives. The full breakdown is at https://veriprajna.com/demos/ai-pricing-compliance.
Same earbuds, matched demand signals, 26% more
The engine under audit is a synthetic stand-in: a LinUCB contextual bandit we call ShopMart Dynamic Pricing, seven price arms, pricing one SKU (the Aura Wireless Earbuds, list $79.00) across a seeded population of 10,000 shoppers. No real retailer or shopper was involved. The engine never receives race or income. It prices on ZIP income index, device tier, referral source, dwell time, cart size, repeat rate, session count, premium membership and hour.
Take two matched cohorts: a high-income-ZIP, new-device cohort (2,880 decisions) and a majority-minority-ZIP, old-device cohort (3,037 decisions), same SKU, with cart size, repeat rate, session count, hour and referral source distributionally matched across the two. The first cohort's displayed price, a cohort mean, is $74.06. The second's is $93.47. The engine produced that 26.2% gap without ever being told anything a lawyer would recognise as a protected attribute, and because these are cohort means over roughly 3,000 decisions each, the gap is systematic.
The same $79.00 earbuds at $74.06 for the high-income-ZIP, new-device cohort and $93.47 for the majority-minority-ZIP, old-device cohort, on the synthetic population. The ZIP and device on each card are the cohort's representative profile; each cohort spans several ZIPs and both phone brands.
The proxy that per-feature checks cannot see
Two of the three proxies the audit flags are the obvious ones. ZIP income index correlates with the protected cohort at |r| 0.95 with mutual information 1.00, a VIOLATION. Device tier comes in at |r| 0.32 and MI 0.08, also a VIOLATION, because it clears the 0.30 Pearson line and the 0.05 MI line the verdict rule uses.
The third only appears when the audit scores pairs. Referral source scores |r| 0.00, MI 0.00, PASS. Dwell time scores |r| 0.17, MI 0.03, PASS. Then the audit computes the joint mutual information of the pair against the protected class and gets 0.73, an interaction gain of 0.71 over the best single feature, and the Referral × Dwell Time row lands a VIOLATION. In this seeded population an organic arrival with a long dwell and a comparison-referral arrival with a short dwell both mark the protected cohort; the other two combinations mark the advantaged one. Only the pair separates the groups, and an engine that carries cross-terms (many real ones do) can price on it.
Referral and Dwell Time each PASS on their own rows two below the interaction row; the Referral × Dwell Time interaction row carries a joint mutual information of 0.73 and a VIOLATION, on the seeded population with its planted proxy structure.
This is why the standard defence fails. The demo's benchmark view runs the fairness-through-unawareness baseline: drop ZIP and device, retrain, re-score. The four-fifths ratio moves from 0.43 to 0.59 and still fails, with the reason line reading Compound Proxy Still Leaks.
A compliance program that audits pricing inputs one at a time is auditing the wrong object. The compound proxy lives in the pair, and joint mutual information over the pair is what reaches it.
An external legal standard, computed in code
Flagged inputs only become a case once population-level harm is measured, so the audit ends at a gate built on an external legal standard, the EEOC four-fifths rule (29 CFR 1607.4(D)), adapted to price tiers. Favorable means the not-top price tier. On this engine 36% of the protected cohort receives the favorable tier against 83% of the advantaged cohort. 0.36 over 0.83 rounds to 0.43, under the 0.80 threshold, Fail. Sixty-four percent of the protected cohort sits in the top price tier and the mean overcharge runs +15.6%.
Every one of those numbers, every threshold comparison and every VIOLATION, ABSTAIN or PASS verdict is computed in deterministic numpy outside the agent layer. Two agents, a Feature Auditor and an Adversarial Challenger, write the explanatory notes under the table. They cannot set or change a verdict, and no model is allowed to decide whether 0.43 is under 0.80. The audit also declines to flag everything: premium membership correlates mildly with the protected cohort (|r| 0.24) and is also a genuine loyalty signal, so the code returns ABSTAIN and routes it to legal review instead of auto-removing it. Cart size, repeat rate, session count and hour all PASS.
0.36 over 0.83 gives 0.43 against the 0.80 threshold, on the synthetic run. The dial and its four tiles carry the same deterministic gate result the hero badge now shows as Gate Failed · 0.43 < 0.80 (visible behind the dialog).
The cheap fix gets gamed
The instinctive remediation is a cap: no price above 115% of a fair reference. On this engine it costs 0.2% of revenue and still fails the gate at 0.59, because a revenue-maximizer treats a ceiling as a target and 29% of the protected cohort ends up priced within 1% of the cap. Fairness-aware reward shaping, which pulls every price continuously toward a proxy-free reference price and leaves no edge to price up against, clears the gate at 0.82 for a measured 1.3% of revenue. That revenue figure belongs to this synthetic engine and scenario, and we do not offer it as anyone's real cost of fairness.
Two fixes side by side on the synthetic run. The cap is cheaper by roughly a point of revenue and fails anyway, because the engine re-prices 29% of the protected cohort to just under it.
The receipt for the CID
Then Equity seals the record. The CID-ready evidence pack is a JSON document with a printable HTML version: the engine name and version, the size of the population audited (10,000 decisions), all ten inputs with their findings and rationale, the gate, the remediation result, and a regulatory mapping (a fixed table, no model prose) that attaches each of the three VIOLATIONs to five regimes: the EEOC four-fifths rule, the New York Algorithmic Pricing Disclosure Act (effective November 10, 2025, civil penalty up to $1,000 per violation), the Colorado AI Act (SB 24-205, effective June 30, 2026), EU AI Act Articles 13 and 14 (high-risk obligations from August 2, 2026), and FTC Act Section 5. The abstained input maps to a single legal-review line. Because that mapping is a fixed table and every verdict feeding it was set in code, the pack stays filable however good or bad the next model turns out to be. A SHA-256 digest of the pack body makes the record tamper-evident. Equity provides the evidence; the client's legal team makes the call.
Ten inputs recorded, the gate before and after, four findings mapped (three VIOLATIONs and the ABSTAIN), and the SHA-256 digest, all from the synthetic audit. The hash changes on every export because the pack carries its generation timestamp.
The company that never logged the right data answers a Civil Investigative Demand with months of forensic extraction. The company that ran the audit answers with a file.
What the labeled synthetic set is evidence of
On the labeled synthetic set the audit recovered 3 of 3 planted proxies with 0 legitimate signals wrongly flagged and 1 of 1 dual-use signal correctly abstained. Those figures are a self-check against structure we planted ourselves. Real pricing logs are confounded, and nobody can ethically A/B-test charging demographic groups different prices, so on an engagement the same machinery hands counsel evidence to weigh; the verdict of intent stays with them. Equity does not set prices and does not replace Pricefx, PROS, Zilliant or Competera; it is designed so a client's engine can be swapped in behind an adapter, and in the demo the LinUCB bandit is the engine.
One exercise for a pricing or legal-ops team this quarter: list every input your engine prices on, then ask whether any pair of them has ever been tested jointly against a protected class rather than each on its own. If the answer is no, the referral-by-dwell row above is the finding nobody has looked for yet. The audit table, the gate and the evidence-pack walkthrough are at https://veriprajna.com/demos/ai-pricing-compliance. We are still debating whether a CID pack should ever carry a Recommended Control label, as the console does, or lay out both controls with their measured costs and leave the choice to counsel. If you have sat on the legal side of a remediation memo, you will have a view on which one survives discovery.