A fitter on a customer’s driveway taps Done on the wrong job. Until 25 October that tap was permanent. A mistaken Can’t complete was worse: the job dropped straight back onto the dispatcher’s To place pile with no reason attached.
TyreStack is our software for mobile tyre fitters: a desk and scheduling board for the office, and a phone app for the fitter in the van. On 24 October we ran a second audit of the scheduling side, as five independent read-only reviews, one per angle. Its verdict was plain. The scheduling engine’s hard rules are strong, but the system was not yet safe for a first paying fitter. Two of its findings are below, and both come down to software claiming something it could not back up.
Thirty seconds, if it is honest
An undo button is easy to build badly. The easy version remembers the last state and puts it back. But Done is not just a status. It can take tyres off the van’s stock and settle a payment. An undo that flips the status back without un-fitting the tyre leaves the stock count wrong. One that pretends to reverse a payment already taken is a lie in the money records.
So the server decides, at the moment of the tap, whether an undo would be honest. When a fitter taps Done or Can’t complete, it saves what the job looked like just before: its status, its slot on the board, the van’s running order for the day and any overrun. If nothing irreversible happened, the reply carries an undo deadline 30 seconds ahead. If stock came off the van, reserved stock was released, or the job was paid and invoiced, the reply carries no deadline, and the app offers no button at all.
Inside the window the undo is checked again when it arrives. It is refused if the 30 seconds are up, if it comes from a different fitter, or if the office has changed the job or reordered that van’s day in the meantime. A thumb slip in a driveway must not overwrite a dispatcher’s newer decision. Every refusal is one plain sentence that ends the same way: “Stock has been taken off the van. Ask the office to put it right.”
Why 30 seconds? The audit suggested 10 to 30. We took the top of that range and turned down anything longer, because stock and payments move on, and the longer the window stays open the more often the honest answer becomes no. An open-ended undo would mostly be a button that refuses.
The same change added “do this one later”. A fitter can now leave a job they have not started: it keeps its slot on the board, moves to the end of their own list, and the board flags who left it and when. Before, the only way to leave a job was to fail it. A Can’t complete now carries the fitter’s reason onto the card on the board, so the dispatcher sees why the job came back.
One detail we did not expect. The table of fitter events has a check on its allowed event types, and that check cannot be widened on a live Durable Object without rebuilding the table. So undo and defer have two small tables of their own. Older versions of the phone app ignore the new fields.
The server side went to production on 25 October and its six post-deploy checks passed. The phone app’s Undo and Later buttons, and an “Are you sure?” on Done, were not built yet on 26 October. The contract went first on purpose, so the app is built against an API that already exists and already refuses correctly.



The map was guessing
The audit’s first finding, marked to fix before anything else, had nothing to do with buttons. A job created at the desk had no map pin, and no code anywhere looked an address up. So the board put each one at a made-up point: a hash of the postcode turned into an angle and a distance from the centre of the fitter’s patch. The point was stable, so the same postcode always landed in the same wrong place. And it was labelled with postcode precision, so the arrival window promised to the customer looked exact.
Everything downstream was priced on that point: drive times, run order, the one-hour windows. The road-time work that came before had only made the times between invented points more precise.
A fair question is why software that labelled a guess with postcode precision got this far before anyone caught it. The honest answer is the stage: there was no paying fitter and no real customer on TyreStack yet, only our own demo data and a second read-only audit done on purpose before a first launch. To our knowledge, nobody outside Mediant had been told a wrong arrival hour. That is exactly why the audit marked it fix-first rather than fix-eventually, and the trigger that would turn this from a pre-launch finding into a live incident, a real booking confirmed on an invented point, is the one we closed before it could happen.
The fix shipped on 24 October. A background job sends the postcode on its own, with no name, phone number or street, to postcodes.io, a free service that needs no key, and caches the centre point it returns. A postcode centre is good to about a street, which is enough for a one-hour window. A dispatcher’s own pin still wins. Until the lookup answers, the job keeps a made-up point but is marked approximate: the offer says “about” and the board asks for a pin. A failed call is retried every five minutes, and nothing waits on it.
We looked at paid geocoders with house-level accuracy and passed for now, on cost and because a postcode centre already gets a one-hour window right. If arrival times turn out wrong in practice, that is the next step. postcodes.io only ever sees a postcode, but that still makes it a processor of address data, so it goes on our sub-processor list before any fitter signs up.
The tests for the new lookup passed, 15 of 15, and it deployed to staging the same evening. We have not yet watched it place a real postcode there, because the staging sign-in is gated and a plain request only proves the site answers. That check, and the Undo button on the phone, are the next two jobs.



