The seat map bounded a booker by what the hall had left and by nothing else, so a per-order limit was invisible on it: the booker pressed, the click was posted, the engine refused it under the slot lock, and the answer came back as a message. Every press past the limit cost a request that could not have landed.
What ships. The allowance is configuration and the same for everybody, so it travels in the shared availability document, per tariff, beside the prices. How much of it one booker has left cannot travel there at all: that document is kept for seconds and served to every visitor, and a remaining count in it would hand one booker's basket to the next. So the browser subtracts what it already holds, which it knows exactly, its own seats plus its own block units, and the bound is exact with no extra request.
Every gesture on the plan asks it.
- A block's stepper stops at the lower of what the area has left and what the allowance leaves, and states which of the two stopped it, in the words the booking page uses for the same rule.
- An area's outline inherits it by calling that stepper, and a press it cannot honor is answered rather than swallowed.
- A click on a seat asks it too. That was the one gesture with no guard at all.
- Repricing a held seat asks it of the tariff the seat is moving to.
The allowance is per tariff, so wherever the sentence is read away from the control it belongs to, it names the tariff it is about. Under a stepper the offer's own row already names it; in the message region beside the plan there is no such context, and a bare limit over a hall of several tariffs says nothing about which one.
The engine stays the authority. The bound in the browser is an optimistic guard, and it is deliberately looser than the engine rather than tighter: an attachment on a resource caps every tariff it offers together while the plan subtracts per tariff, and a policy reaching wider than one session cannot be computed from one map at all. Looser is the only safe direction, since a guard stricter than the engine would refuse a click the engine would have taken. The refusal under the slot lock is what enforces the rule.
Two defects found while building it, fixed here. An area whose places the house gives out is asked for as a party, so the whole ask was refused whatever the reason, and a run past a limit left the booker with nothing instead of what the limit allowed; a rule that caps a count publishes the number, so the ask is now remade at that number, while a refusal that names no number still refuses whole. Separately, the settled half of the availability document is held until something invalidates it, and the tags it carried cover only what an availability figure is made of: a ceiling is read from the resource and its type as well, and so are the prices the payment layer fills through the same seam, so an operator lowering a limit or changing a price on the resource was answered with the old entry indefinitely.
AI-Generated: Yes (Claude Code wrote the code and the tests, ran the linters and the test suites, and drafted this summary; I reviewed it before posting.)
Issue fork yoyaku-3616821
Show commands
Start within a Git clone of the project using the version control instructions.
Or, if you do not have SSH keys set up on git.drupalcode.org:
Comments
Comment #2
mably commentedCorrected the summary: both kinds of area offered by quantity carry steppers in the panel, so the ceiling belongs to the stepper they share rather than to an outline. An assigned area is listed with its own steppers as soon as the booker holds one of its seats, and from the start where it has no outline.
AI-Generated: Yes (Claude Code drafted this correction; I reviewed it before posting.)
Comment #4
mably commentedComment #5
mably commentedComment #7
mably commented