This edition is dated 20 October 2026, and the litigation it describes stands as of that date. Its validation figures come from one rider’s Lyft records and from a synthetic market of invented events, sellers, platforms and buyers. The RESALE Act’s lines apply from 1 January 2027. The protocol measures prices against the law’s numbers and is not legal advice.
Purpose and legal frame
This protocol runs the Continuous Collective Intelligence (CCI) engine over resale ticket prices for live events in the District. It grew out of one rider's Lyft records, the records behind the Field Work Brief The Klando Cartel, where six tests found the fingerprint of a price that no posted input explains. For a ticket, the posted basis is not a rate card but the ticket's own first sale.
DC's Restricting Egregious Scalping Against Live Entertainment (RESALE) Amendment Act of 2026, D.C. Law 26-181, applies from 1 January 2027 to concerts, theater, comedy and other live events. Sporting events of DC teams and movie screenings are exempt (D.C. Law 26-181). Its lines are numbers an engine can check:
| Provision | Rule | D.C. Code |
|---|---|---|
| Resale price | No more than the total price of the first sale, fees and taxes included, plus 10% | §28-5506(b) |
| Marketplace fee | No more than 10% of that first total | §28-5506(c) |
| Disclosure | The total price and every itemized charge, at each listing and each step of purchase | §28-5502(a) |
| Speculative tickets | No sale or listing of a ticket the seller does not hold | §28-5503 |
| Surveillance pricing | No price, fee or discount set from personal data gathered by electronic surveillance | §28-5509 |
| Records | High-volume resellers keep original and final prices for 3 years; exchanges keep records open to inspection | §47-2890.04 |
A $100 ticket can therefore resell for $110 plus a $10 marketplace fee, $120 at most to the buyer (DC Council; TicketNews).
On 14 October 2026 the Ticket Policy Forum, SeatGeek, Vivid Seats, Gametime and TickPick sued to block the whole law, Ticket Policy Forum v. District of Columbia, No. 1:26-cv-03577, before Judge Carl J. Nichols, and asked for a ruling by 10 December (Music Business Worldwide; docket). On 16 October the National Association of Ticketing Professionals and two brokers filed a narrower suit against the price ceiling alone, No. 1:26-cv-03620 (TicketNews). Among their claims: marketplaces cannot verify what a ticket first sold for, the law reaches sales outside the District, and its record-keeping is an unreasonable search. The section on the complaint's claims answers the technical half of those.
The protocol sorts every finding into one of two grades:
- Bright line
- A breach of a rule as written: a price over the 110% line, a fee over the 10% line, a listing before the seller held the ticket, a missing disclosure, or a checkout total above the listed total. With a verified first-sale price, one record is enough.
- Pattern
- Evidence that prices are set by something other than the ticket and the event: different prices to different buyers for the same seat in the same minute, reprices faster than any input moved, wide spreads on identical seats, and independent sellers' prices moving in lockstep. These build an inference across many records, and no single record proves one.
In this protocol a price is rigged when it breaks the law's line, or when it moves with the buyer or with coordination among sellers rather than with the ticket. The engine reports the evidence and its grade. Whether the conduct is unlawful is for the District's lawyers and the court.
Price model
For a resale ticket, each CCI term has a fixed meaning:
| Term | For a resale ticket |
|---|---|
| Fair basis, B (the CCI's Pc) | The total of the first sale: face value plus the primary seller's fees and taxes |
| Price line | 1.10 × B, the most a reseller may ask (§28-5506(b)) |
| Fee line | 0.10 × B, the most a marketplace may add (§28-5506(c)) |
| Price charged (Pa) | What the buyer is shown and pays: the resale price plus the marketplace fee |
| Multiple | The resale price divided by B. 1.00× is the first-sale total and 1.10× is the line |
| Premium, E | Pa − B, what the buyer pays over the first sale. Up to 0.20 × B is lawful |
| Legal excess | The price over 1.10 × B, plus the fee over 0.10 × B, plus anything added at checkout. This is the restitution base |
| Acute part, S(t) | The median premium, as a share of B, among tickets in the same time-to-event band and the same scarcity state (the primary still on sale, or sold out) |
| Discrete part, D(u) | Each ticket's premium less S(t): what the seller, the buyer or the platform adds |
The time-to-event bands are over 30 days, 8 to 30 days, 2 to 7 days and the final 48 hours.
In the Lyft reading the card was the basis, and anything over it was premium. For tickets the law already allows a premium, up to 10% on the price and 10% in fees, so E has a lawful zone from zero to 0.20 × B and a legal excess beyond the two lines. At 1.10 the CCI question and the legal question become the same question.
S(t) still matters inside the line. Resellers argue that their prices follow demand: a sold-out show, the last days before it. S(t) measures how much of the premium time and scarcity explain, and D(u) is what they leave unexplained. If a sold-out primary explained resale prices, S(t) would carry most of the variance. In the Lyft records the hour and the transit state carried a tenth of it.
Data intake
The engine reads five record types, one JSON object per line. Each comes from a source the law already creates or the District can run itself.
| Record | Key fields | Source |
|---|---|---|
| Ticket | ticket_id, event_id, event start, venue in DC, exempt, section, row, seat, face, primary fees, taxes, basis source, basis commitment | The issuer's record of the first sale, the reseller's own records (§47-2890.04(b) requires 3 years of original prices), or the buyer's receipt |
| Listing snapshot | listing_id, ticket_id, seller, platform, time, price, fee, total shown, itemized, original price shown, seat shown, time the seller came to hold the ticket | The exchange's records (§47-2890.04(c)), or time-stamped captures of public listing pages |
| Audit quote | quote_id, listing_id, time, audit profile and its segment, price, fee, total shown, checkout total, shipping | The District's own paired-quote program, using registered test profiles |
| Sale | sale_id, listing_id, time, price, fee, buyer total | The exchange's records |
| Primary inventory | event_id, time, tickets still on sale | The issuer, or captures of the primary sale page |
The same listing appears once per snapshot, so a reprice is a new row with the same listing_id. Identical seats share a comparison key of event, section and row.
Every ticket's basis carries a source: issuer-attested, reseller record, buyer receipt or missing. A missing basis is never estimated. The engine records it as a data gap, because the price line cannot be tested without it.
Parties are named by identifiers rather than personal data: a licensed reseller by its District license (§47-2890.02), a platform by its business license, and an audit profile by its registration. In production each would be a decentralized identifier (DID) with a signing key, so a record can be traced to the party that made it. No buyer's identity is needed for any test.
Tests
Eleven tests run on every batch. The six bright-line tests read the law's own lines. The four pattern tests are the CCI fingerprint from the Lyft reading. Data gaps are reported, never filled in.
| Test | Flags when | Default | Grade | Source |
|---|---|---|---|---|
| Price cap | Resale price > 1.10 × B | half-cent tolerance | Bright line | §28-5506(b) |
| Fee cap | Marketplace fee > 0.10 × B | half-cent tolerance | Bright line | §28-5506(c) |
| Disclosure | No total shown, charges not itemized, or no seat location | any | Bright line | §28-5502(a) |
| Original price | The first-sale price is not shown with the listing | any | Bright line | §28-5506(a) |
| Checkout add-on | The checkout total is above the total shown, less disclosed shipping | over half a cent | Bright line | §28-5502(a)–(b) |
| Speculative listing | First listed before the seller held the ticket | any | Bright line | §28-5503 |
| Personalization | Paired quotes for the same listing, seconds apart, differ by segment of the asker | within 120 s; difference over $0.50 or 1%; 5 or more differing pairs; sign test p < 0.05 | Pattern | §28-5509; CCI D(u) |
| Velocity | The multiple moves more than τ with no primary-inventory move to explain it | τ = 50% within 24 h; an input moved = inventory down 50% or more | Pattern | CCI S(t) |
| Dispersion | Identical seats on offer at the same time carry widely spread multiples | coefficient of variation over 0.30, 4 or more seats, read daily | Pattern | CCI |
| Convergence | Independent sellers' multiples collapse together above the line, and their reprices land minutes apart | 3 or more sellers; variance down 75%; last mean over 1.10; half of reprices within 5 min of another seller's | Pattern, referral | CCI σ² → 0 |
| Data gaps | No basis on record; no possession time; a large reprice where an input did move | any | Data gap | §47-2890.04 |
The price-cap and fee-cap tests run on both listings and sales. A listing over the line is an offer the law bars, and a sale over the line is money a buyer paid. Only sales count toward restitution.
The pattern thresholds are starting points. The 50% velocity line and the 0.30 dispersion line come from the Lyft reading, where the Braddock Road trip moved +174% in a night and its spread reached 0.38. They are meant to be tuned on DC's own listings once the law applies, and every run records the values it used.
The personalization test never uses a consumer's data. It uses the District's own test profiles, which differ only in the attribute under test (a ZIP code band, a device, a browsing history), and asks whether the same listing in the same minute costs more for one of them. An exact sign test keeps chance from counting as a pattern.
Decomposition
The engine splits each paid premium into the part the moment explains and the part it does not:
- Express each premium as a share of its basis, so a $40 ticket and a $400 ticket compare.
- Group the premiums into cells by time-to-event band and scarcity state.
- Set S(t) for each ticket to its cell's median premium.
- Set D(u) to the ticket's premium less S(t).
- Report the share of the premium's variance that each part carries.
A market priced by demand puts most of the variance in S(t): tickets in the final 48 hours of a sold-out show cost more, and tickets a month out cost less. A market priced by who is selling, who is buying or which platform is showing the price puts it in D(u).
Two measurements so far:
- The Lyft records
- S(t) carried 10% of the variance and D(u) 88%.
- The synthetic market
- S(t) carried under 1% and D(u) 98%. Its planted anomalies all belong to particular sellers and platforms, so this is the expected result.
On real DC listings the split answers a question the case turns on: whether resale premiums follow the event or the seller.
D(u) is a residual. On listings and sales it mixes the seller's pricing with anything the cells do not capture. The direct measure of D(u) for the buyer is the personalization test, where two test profiles quote the same listing within seconds of each other.
Evidence packets
Every finding becomes one evidence packet. A packet holds:
- the finding: test, grade, rule, subject (listing, sale, seller, platform), the measured values and the thresholds;
- the source records the finding rests on, in full;
- a SHA-256 hash of each source record, taken over its canonical JSON (sorted keys, no spaces);
- the parameters in force and the engine version;
- the packet's own hash, over everything except the records themselves.
The packet hashes are the leaves of a Merkle tree. Its root seals the run: one 64-character value that changes if any byte of any record or finding changes. Each packet carries its Merkle path, so the District can hand a court one packet and prove it belongs to the sealed run without handing over the rest. The verify command re-hashes every record and packet and checks the root. In testing, changing one price in one record made verification fail.
Restitution is computed from bright-line findings on completed sales only: the price over 1.10 × B, the fee over 0.10 × B and any checkout add-on, summed by seller and by platform. Offers over the line are counted and reported, but no buyer paid them, so they carry no restitution.
For chain of custody, each run's seal (root, time, engine version, parameters, dataset name) is filed with the Department of Licensing and Consumer Protection when the run is made. A later dispute over what the engine saw is settled by re-hashing.
Privacy and proof
The protocol is built so the District can check prices without collecting more than the check needs.
Basis commitments
At the first sale, the issuer commits to the ticket's total: a hash of the ticket ID, the total in cents and a random salt. The commitment travels with the ticket through every resale. Anyone can see the commitment, but only someone given the opening (the salt and the total) can read the price behind it, and an opening that does not match is caught at once. A listing that carries a commitment has an original price that can be checked, not just claimed.
Range proofs
In production, a reseller proves that its price is no more than 1.10 times the committed basis without revealing the basis. That is a zero-knowledge range proof, for example Bulletproofs over Pedersen commitments. The prototype does not include one. It ships the interface and a transparent verifier that checks the same claim by opening the commitment, which suits a disclosure to the Department under §47-2890.04, where the regulator may see the basis anyway. The prototype says so in its code and its output.
Merkle inclusion
Sealed runs let the District show one packet, with its path to the root, instead of the whole ledger.
Decentralized identifiers
Sellers, platforms and audit profiles sign their records with keys tied to DIDs. A record's origin can then be proved without a name in the payload.
No consumer data
The personalization test uses the District's own test profiles, not shoppers' data. An audit of surveillance pricing that ran on surveillance would defeat its own purpose.
Architecture
The four layers come from the CCI thesis: ingestion, a continuous processing matrix, audit logic and a restitution interface. The prototype engine builds each one in plain Python with no outside libraries, so it runs anywhere and every line can be read.
| Module | What it does |
|---|---|
resale.py |
The DC record schema, the market loader and the six bright-line tests |
core.py |
Observations, the extraction fingerprint, the S(t) and D(u) split, and the velocity, dispersion, personalization and convergence tests |
ledger.py |
Evidence packets, the sealed Merkle root and restitution |
commit.py |
Basis commitments, Merkle paths and the range-proof interface with its transparent verifier |
report.py |
The run's report, summary, packets and seal |
adapters/lyft.py |
Reads ride records against a posted rate card, for calibration |
synth.py |
A seeded synthetic DC market with planted anomalies |
params.py |
Every threshold, overridable per run |
Commands: synth builds the test market, resale runs a market folder, rides runs ride records, and verify re-hashes a finished run. In production the same tests would run on a stream (the thesis names Kafka and Flink) instead of in batches, and the ledger root would be filed at the close of each run.
Validation
The engine was checked twice: once on real records it had to reproduce, and once on a synthetic market where every anomaly was planted.
Calibration on the Lyft records
Run through the ride adapter, the engine reproduced the Klando reading:
| Measure | Klando reading | Engine |
|---|---|---|
| Rides measured | 58 | 58 |
| Net premium | $27.60, 2.6% of fair | $27.60, 2.61% of fair |
| Rides above, below and at card | 21, 23, 14 | 21, 23, 14 |
| Median multiple and range | 1.01; 0.44 to 2.14 | 1.01; 0.44 to 2.14 |
| Spread on the Braddock Road trip (coefficient of variation) | 0.38 | 0.377 |
| Largest surge velocity | +174% | +174% |
| Variance carried by S(t) and D(u) | about a tenth; almost nine tenths | 0.10; 0.88 |
| Fees with no ride | 9, $56.15 | 9, $56.15 |
The check also caught an error in the first reading. It had given the 21 above-card rides $109.53 of premium, but that figure summed every positive premium, including rides within a dollar of the card. The engine gives $105.39. The rider's records stay private, so this check runs only where the ride file is held.
The synthetic market Synthetic
One seeded run: 529 tickets, 611 listings with 6,694 price snapshots, 211 sales and 480 audit quotes, across five invented events and three invented platforms.
| Planted | Planted count | Engine found |
|---|---|---|
| One seller asking 1.4× to 2.0× on floor seats | 30 listings, 12 sold | All 30 and all 12; $1,220.52 paid over the line |
| A $9.00 minimum fee on one platform | Every sale where 10% of basis is under $9.00 | 46 fee findings (13 on sales), all on that platform |
| A 7% higher price shown to high-income test profiles on one platform | 67 of 80 pairs | That platform only; 67 of 67 differing pairs higher for that segment, p < 0.001 |
| Four sellers holding one section and repricing together toward 1.48× | 12 listings | One convergence finding: that section, those four sellers, variance down 100%, every reprice within minutes |
| Listings made before the seller held the ticket | 15 | 15 |
| $4.50 added at checkout | 18 quotes, 5 sales | 23 |
| +80% reprices with nothing in the market moving | 10 | 10 velocity patterns |
| Original price hidden on early listings | 8 | 8 |
| A real input: a primary sell-out, then +60% reprices | 42 listings | No velocity patterns; 40 kept as data gaps (2 listings had no basis) |
| Exempt and out-of-District events at 2× to 3× | All of them | No findings |
Every bright-line finding matched a direct calculation of the law's lines over the same records: none extra, none missed. All 9 dispersion findings fell in rows that held a planted listing. The test suite passes on nine seeds.
A synthetic market shows that the engine finds what it was built to find. It says nothing about how often these things happen in DC. That takes real listings after 1 January 2027.
Technical answers to the complaint's claims
Several claims in the Ticket Policy Forum complaint turn on what can and cannot be known about a ticket's price (complaint). This section answers only the technical half. Whether an answer carries legal weight is for the District's lawyers.
| The claim | What the protocol shows |
|---|---|
| Marketplaces "do not know" what the first buyer paid and cannot make the issuer say (¶¶32, 48) | The issuer commits to the first-sale total at the moment of sale, and the commitment travels with the ticket. The complaint itself asks why issuers, who hold the figure, were not made to pass it along (¶66); a basis commitment is that hand-off. High-volume resellers must already keep their original purchase prices for three years (§47-2890.04(b)). Where no basis exists, the engine reports a data gap and tests nothing. |
| Dynamic, bundled and free tickets have no single first price (¶49) | Each ticket carries its own committed total, so seat-by-seat dynamic prices are no obstacle. A bundle is committed at its allocated price, or flagged as a data gap. |
| The law reaches sales between parties outside the District (¶33) | The engine scopes on the event: a venue in DC and not exempt. It never needs the buyer's or the seller's location. In testing, events outside DC and exempt events produced no findings. |
| Publishing an unverifiable original price is compelled speech (First Amendment count) | With a commitment, the price shown can be checked against the issuer's record by anyone given the opening. The listing can say whether its original price is issuer-verified. |
| Keeping and producing records is an unreasonable search (¶¶126–129) | The Department can receive sealed evidence packets for flagged listings, with Merkle paths, instead of whole ledgers. In production, range proofs show compliance without revealing the basis at all. |
| Marketplaces are not liable for sellers' listings (Section 230 count) | The fee, disclosure, checkout and personalization tests read the exchange's own charges and its own pages, not what a seller wrote. Each finding names both the seller and the platform. |
The engine also gives the District a measured answer to the policy argument that prices simply follow demand. The S(t) and D(u) split shows how much of the premium the event's timing and scarcity explain.
Limits and open questions
- Pattern thresholds are not legal standards
- They were set from one rider's records and a synthetic market. They need tuning on DC listings after 1 January 2027, and every run records the values it used.
- Convergence is a referral, not proof of agreement
- Shared pricing software or shared public information can also make prices move together. The test marks where to look.
- The personalization test can be gamed
- A platform that spots test profiles can show them a clean price. Profiles need to look like ordinary shoppers and be rotated, and the test should run on more than one attribute.
- The prototype's range check is not zero-knowledge
- It opens the commitment to the verifier. A real range-proof backend goes behind the same interface before any reseller is asked to prove compliance privately.
- Basis commitments need the issuer
- Until issuers commit at the first sale, the basis comes from reseller records and receipts, and every missing one is a data gap.
- The lines can move
- The Mayor may change both lines by rule from 2028 (§28-5507(b)). The engine takes them as parameters.
- One reading to settle
- The law's text and its press coverage agree that the price line is 110% of the first-sale total and that the marketplace fee is a further 10%, so a buyer pays at most 120%. The engine applies them as two separate lines. Counsel should confirm that reading.
- Not legal advice
- The protocol measures prices against the law's numbers. Whether particular conduct breaks the law is for the District's lawyers and the court.
The engine’s source is held by Lexeme LLC. The CCI Console runs the same tests in a browser on the synthetic market, and nothing loaded into it leaves the browser.