Sharpen ordering domain model and close a cancellation race

CONTEXT.md described Order Item cancellability and Order completion
in ways the code didn't actually implement (cancellability only
covered the first Preparation Step; completion required pickup, not
any terminal state). Corrected the glossary to match intended
behavior, added Guest Access Token and Charge as formal terms, and
recorded the single-Charge-per-Order design as an ADR.

Also closes a real race in cancelOrderItem: a Machine could claim a
queued Step between the cancellability check and the delete, letting
an already-cooking item get cancelled and refunded. The delete now
atomically re-checks status = 'queued'.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
2026-09-09 19:48:04 +02:00
co-authored by Claude Sonnet 5
parent 456c3acda5
commit d291312139
4 changed files with 30 additions and 5 deletions
+1 -1
View File
@@ -1,3 +1,3 @@
# Order Items are independent, not the Order
Preparation, queuing, pickup, and cancellation are all tracked per Order Item, not per Order. An Order is just a bundle that is "complete" once every Order Item in it has been picked up — but each Order Item cooks on its own Machine, becomes ready on its own, gets notified and picked up on its own, and can be cancelled on its own (locked only once its own first Preparation Step starts). We chose this over treating the Order as the atomic unit because items in the same order can have very different cook times (a pizza vs. a burger); forcing them to stay in lockstep would mean a finished item goes cold waiting on a slower one, or a customer loses the ability to cancel a not-yet-started item just because a sibling item already started cooking.
Preparation, queuing, pickup, and cancellation are all tracked per Order Item, not per Order. An Order is just a bundle that is "complete" once every Order Item in it has reached a terminal state — but each Order Item cooks on its own Machine, becomes ready on its own, gets notified and picked up on its own, and can be cancelled on its own (locked only once its own current Preparation Step is claimed by a Machine). We chose this over treating the Order as the atomic unit because items in the same order can have very different cook times (a pizza vs. a burger); forcing them to stay in lockstep would mean a finished item goes cold waiting on a slower one, or a customer loses the ability to cancel a not-yet-started item just because a sibling item already started cooking.