The notification said one thing and the screen behind it said another
A courier app has to learn about a new job within a second, on a network that drops. Push exists for that, and the app also fetches the same job list whenever it is opened.
Support has a class of ticket nobody can reproduce: the notification says one fee and the job screen says a different one. Both numbers are right — they were produced by two pieces of code that were changed on different days.
- R1Deciding that something is worth telling a courier about is its own judgement: an offer they are eligible for, not every write that touches their record. Whatever makes that decision must send on eligibility rather than on activity.
- R2The body of a push and the body of the app's own fetch describe the same job. They must be produced by the same component, so that a change to how a job is described lands in both at once and cannot land in one only.
- R3When the app asks directly — on open, on pull-to-refresh, after a reconnect — it must be answered by that same component, not by a second implementation that happens to agree today.
Boundaries, outermost first: THE PLATFORM: Job store (offers and fees), an empty slot for the decides this one is worth sending, tier 1, an empty slot for the builds what the message says, tier 1, an empty slot for the answers the app when it asks, tier 2 Outside every boundary: Courier app (pushed to, and asks), Push transport (delivers to devices) Connections: Job store calls decides this one is worth sending — a job changed decides this one is worth sending calls builds what the message says — tell this courier builds what the message says publishes to Push transport — the message Push transport publishes to Courier app Courier app calls answers the app when it asks — on open, on refresh