Where you are. Lesson 11 opened the card machine: cardholder, merchant, issuer and acquirer, coordinated by a scheme, with authorisation in seconds and settlement days later. Lesson 12 followed the money through the fee stack: interchange to the issuer, a margin to the acquirer, the merchant receiving less than the sticker price on every sale. Both lessons watched money flow one way, towards the merchant. This lesson runs the machine backwards. A settled card purchase can be contested, and the contest can end with the money travelling back down the chain it arrived by - which sounds like a violation of module 1’s finality, and turns out to be its sharpest test.
Six weeks later
The jacket never arrives. The cardholder scrolls to the charge in her banking app, taps “dispute”, picks “goods not received” from a menu of reasons, and goes back to her day. Six weeks later, on the far side of the machine, the merchant’s bank debits the merchant’s account for the full purchase amount. Not a request, not an invoice: a debit. The merchant did not authorise it, was not asked, and cannot refuse it.
Hold both halves of that scene. By what right does one bank reach into a settled sale and pull the money back out? And by what mechanics - the purchase cleared and settled weeks ago, and module 1 defined finality precisely so that settled things stay settled? One tap from a customer appears to have reached through all of it. Either finality broke, or something more careful is going on.
The idea in one paragraph
Every card purchase carries a dispute path defined by the scheme’s rulebook: PURCHASED until somebody objects; DISPUTED when the cardholder does; and from there two exits - either the merchant fights and wins, and nothing moves, or the merchant loses and the purchase is charged back. A chargeback is not an undo. The settled postings stand exactly as they were; what the rulebook obliges is a new set of postings, opposite in sign, back through the same chain the purchase travelled - the merchant’s deposit down at the acquirer, reserves relabelled at the central bank, the cardholder’s deposit up at the issuer - while the fees skimmed on the way in stay where they landed. And who finally eats the loss is not answered by the ledger at all: the scheme’s liability rules pick the loser, and the postings simply write the ruling down.
A machine with two exits
Start with the right, because it is the less mysterious half. Nobody reached into anything. When the merchant signed up to accept cards, it signed its acquirer’s terms; the acquirer signed the scheme’s rulebook; so did the issuer. The rulebook is a contract, and among its clauses is this one: a cardholder may contest a transaction, the contest will be judged inside the scheme’s own process, and a lost judgment obliges the money to move back. The debit that stunned the merchant was a contractual term executing. Consumer law in many countries layers protections of its own on top; the machine in this lesson is the scheme’s own, and it is the one that moves the money.
The process itself is a state machine, and a small one. A settled sale rests in PURCHASED. The cardholder’s objection, filed under a reason code - the menu she picked from - moves it to DISPUTED. From there the rulebook allows exactly two exits. The merchant can fight, and the fight has a lovely literal name: representment - the merchant re-presents the transaction to the issuer, this time with evidence attached: a delivery confirmation, a signed receipt, server logs showing the service was used. Convincing evidence kills the dispute where it stands, and not one entry posts anywhere. Or the ruling goes to the cardholder, the state becomes charged back, and the reversal posts. Every transition runs on deadlines the rulebook sets: file inside the filing window, answer inside the evidence window, and a missed deadline loses by default.
Wider than the screen; scroll it sideways.
The figure names the liability holder under each state, because that is what the machine is really tracking. In PURCHASED the cost sits with the cardholder: she paid, the merchant was paid, everyone is square unless somebody objects. In DISPUTED, real schemes typically credit the cardholder provisionally while the contest runs - the issuer fronts the money and takes it back if the merchant wins - so the exposure sits, for those weeks, with the issuer. REPRESENTED puts the cost back on the cardholder, finally. CHARGED_BACK moves it to the merchant: money returned, goods already gone, fees kept.
Notice what this machine is not: lesson 8’s returns. On the batch rail a payment could bounce days later because, on a deferred rail, arrived was not yet final - the return raced the settlement. The card purchase here has no such excuse. It cleared, it settled, and module 1 would stamp it final without hesitation. The dispute machine operates on genuinely settled money, which is exactly why its output must be new postings and can never be a cancellation.
The reversal, leg by leg
The exercise world names its parties by first letter: Ivy the issuer banks carol the cardholder, Acorn the acquirer banks mercury the merchant. The numbers are stylised - a purchase of 100, interchange of 2, an acquirer margin of 1 - round on purpose so every diff reads at sight. The purchase lands as three balanced postings, lesson 12’s fee stack in miniledger form: Ivy posts carol down 100, reserves down 98, equity up 2 - the interchange, banked. The central bank relabels 98 from Ivy’s line to Acorn’s. Acorn posts reserves up 98, mercury up 97, equity up 1. The merchant received 97 of the sticker 100.
The chargeback mirrors the chain, not the amounts. It moves the full 100, and it touches no equity line anywhere. Acorn posts mercury down 100, reserves down 100. The central bank relabels 100 back, Acorn’s line down, Ivy’s line up. Ivy posts reserves up 100, carol up 100. The cardholder is made whole at the sticker price; the interchange and the margin sit exactly where they were banked, unmoved by the ruling.
Finality, unbruised
The last thing the ruling decides is who absorbs the loss, and the ledger does not decide it - the rulebook does. Usually the merchant eats it, as mercury just did. If the merchant has vanished - bust, or fraudulent from the start - the acquirer absorbs it, because the acquirer guaranteed its merchants to the scheme; that guarantee is why acquirers vet merchants the way lenders vet borrowers, and hold rolling reserves against the risky ones. On the other side of the machine, the fraud losses the issuer eats are part of what lesson 12 said interchange funds. Liability is a parameter of the rulebook, not a fact of the postings, and schemes use it as an incentive lever: shifting it, by rule, towards whichever party was best placed to prevent the loss.
Check yourself
1. The chargeback debits mercury 100, yet mercury only ever received 97. Why is the difference not a bug?
The 3 was skimmed on the way in - 2 of interchange banked by Ivy, 1 of margin banked by Acorn - and the rulebook does not refund fees on a lost dispute. The reversal moves the sticker amount so the cardholder is made whole at exactly what she paid, while both banks’ equity lines keep their fee. The merchant’s cash ends down by precisely the fees kept, which is the exercise’s assert: a lost dispute costs the merchant the goods, the money and the fees.
2. Module 1 defined finality as the point after which a payment cannot be unwound by any party. A chargeback moved the money back. Which words in the definition do the work?
“Unwound” and “by any party”. The settled postings stand untouched, and every balance they created was real and spendable in the interval; what the scheme obliges is new postings of opposite sign, appended afterwards - an offset, not an unwinding. Nor is this lesson 8’s batch return, which bounced a payment that had not yet reached finality; the chargeback operates on money that genuinely had. Finality guarantees history; it never promised the absence of remedies.
3. The merchant fights the dispute and wins. What posts to the ledgers at the moment of representment?
Nothing. REPRESENTED is a state transition with no postings: the dispute dies, the cost settles on the cardholder finally, and every balance stays exactly where the purchase left it. The dispute machine writes to the ledger only on its losing exit - which is why the exercise’s memo log grows on a chargeback and stays flat on a representment.
4. The exercise’s state machine raises LedgerError on PURCHASED to CHARGED_BACK. What real rule does that refusal model?
A chargeback exists only as the ruling on a dispute; there is no path in any rulebook from a quiet settled sale straight to a forced reversal. The dispute must be filed first, under a reason code, inside a window, and answered inside another. “Rules-based” cuts both ways: the same rulebook that lets the scheme force money back also constrains exactly when it may. The demo asserts the refusal arrives before a single balance moves.
5. lifecycle.entries only ever grows, and the final assert checks it. What would deleting the purchase rows instead actually break?
Everything built on them. The purchase’s balances were spendable history for six weeks - statements were printed from them, fees were banked out of them, other payments settled against them. Deleting the rows would rewrite a past that other facts already depend on, exactly what double entry exists to forbid: the ledger has no delete, only compensate. The memo log is the proof the exercise keeps - after the ruling there are strictly more entries, never fewer.
Do this
Fifteen minutes, from module-02-domestic-rails; the script adds the repo root to its own path, so the miniledger import resolves on its own. Open code/chargeback.py. The Dispute class walks one purchase over a shared World: a TRANSITIONS table that raises LedgerError on any move the rulebook does not allow, a _post_purchase already written - the three postings above, fees skimmed into each bank’s equity - and a memo log, entries, that every posting appends to. Real schemes credit the cardholder provisionally while the dispute runs; this toy moves money once, at the final ruling, to keep the reversal readable. The demo builds Ivy and Acorn, runs the purchase, then tries to charge back straight from PURCHASED and requires the refusal - refused: rules-based means rules: PURCHASED cannot jump to CHARGED_BACK - before disputing properly and ruling for the cardholder.
Your TODO(you) is _post_reversal: three postings mirroring the purchase chain in reverse - acquirer leg, reserve leg, issuer leg - each moving the full self.amount, posted with self._post(...) so the memo log grows, and self.world.assert_world() at the end. The tempting mistake is to mirror the purchase exactly with the signs flipped, equity legs included; the closing asserts will catch you, because the rulebook does not refund fees - both banks’ equity lines must end untouched.
python3 code/chargeback.py
Green walks the whole lifecycle - purchase, refused shortcut, dispute, ruling - and the closing asserts check every claim this lesson made: carol made whole at exactly 100, mercury’s cash down exactly 3, the interchange and margin still banked, and strictly more memo entries after the ruling than before it. The run ends with the line
a chargeback is a rules-based reversal: compensating entries move the money back, and nothing is ever deleted
The completed version is solutions/chargeback.py; compare after you are green, not before.
What you can now do. You can run a settled card purchase through the dispute machine end to end: file the dispute, name the two exits, and post the losing one as three balanced entries of opposite sign back down the chain the purchase travelled. You can say precisely why the reversal is a new posting and not an undo - the settled entries stand, the log only grows, and finality holds because “cannot be unwound by any party” was never the same claim as “can never be offset” - and you can read who ate the loss straight off the closing balances: cardholder whole, fees where they landed, merchant down the goods, the money and the fees. Lesson 14 climbs one layer up, to the wallets and pay-by-bank apps that dress these rails in better clothes - where the question that cuts through every pitch is one you can now answer for cards: which rail settles this?