"Capacity is always required, there is no unlimited" was settled on #34
and enforced in #62 — but as a single number on the event. Since v1.6.8
capacity is per-wave and `event.amount_tickets` is a derived roll-up
(`sync_event_ticket_waves`), so the rule had nothing holding it up at
the level organisers actually set: the wave form's capacity input had no
minimum, and nothing on the backend checked one at all.
A zero-capacity wave can never be active — `get_active_ticket_waves`
requires `amount_tickets > 0` — so it is the wave-level form of exactly
what #62 removed: an event that looks on sale but refuses every
purchase, on the card and at checkout both.
`_validate_wave_capacity` now runs on create and update. Two details
that matter:
- it checks `ensure_ticket_waves(data)` rather than the raw list, so an
event submitted with no waves is checked through the primary wave it
is about to be given, not vacuously passed
- on an edit it only checks waves NEW to the event. Selling out is the
legitimate route to zero, and rejecting it would make a sold-out event
uneditable — including the legacy zero-capacity rows this rule exists
to let organisers fix
Frontend: the wave dialog's capacity input gains the `min="1"` and hint
the event-level field already had, and a new wave opens at 1 rather than
0. That default uses `??`, not `||` — a sold-out wave holds 0 and must
keep showing it instead of silently regaining stock when saved.
Also drops the stale `0 = unlimited / not ticketed` contract still
documented on `CreateEvent.amount_tickets`, which has not been true
since #62.
6 new tests; 120 pass. ruff, black, prettier clean; mypy error set
unchanged from baseline.