Preconditions
Organizer can edit access types for the fixture event; the event has at least one access type with current registrations.
Happy path / Lifecycle
Open the quantities and windows editor.
Each access type row shows capacity, sold/claimed count, remaining count, availability start, and availability end.
Increase capacity and narrow the sale window.
The form validates that capacity cannot drop below claimed count and the end time must be after the start time.
Save and notify downstream surfaces.
The admin list updates immediately and public registration gates use the new window and remaining inventory.
Failure modes
Permission denied at the right boundary
Trigger: viewer submits a quantity/window update.
Resolution: 403 response, no inventory mutation, and no hidden access-type details are returned.
Cross-tenant isolation
Trigger: tenant A user guesses tenant B access type.
Resolution: 404 response masks existence and the UI shows only a generic not-found state.
Soft-delete leaves audit trail
Trigger: organizer removes an unused access type from the quantity table.
Resolution: tombstone plus audit row with prior capacity and window state.
Archive vs delete distinction
Trigger: organizer wants to stop future registrations.
Resolution: archive/close-window is reversible; delete is reserved for unused types and uses destructive confirmation.
Edit lock during publish
Trigger: publish reads inventory while organizer saves a new capacity.
Resolution: publish snapshot wins and the edit receives a conflict warning.
Audit row on every state change
Trigger: capacity, start, end, archive, or delete changes.
Resolution: audit row exists for every successful mutation with before and after values.
Two organizers concurrent
Trigger: one organizer lowers capacity while another extends the window.
Resolution: version conflict prevents silent overwrite; both see final state after refresh.
Undo window for destructive actions
Trigger: organizer closes or archives availability.
Resolution: undo toast restores the prior capacity/window state within 10 seconds.
Capacity below claimed
Trigger: organizer sets capacity lower than already claimed tickets.
Resolution: inline validation blocks save and states the current claimed count.
Window crosses timezone boundary
Trigger: organizer edits start/end around DST or timezone changes.
Resolution: date range picker stores UTC correctly and displays the event timezone explicitly.
Downstream messaging gap
Trigger: window change affects guests who previously saw a different close date.
Resolution: admin sees a messaging gap panel until attendee notification behavior is implemented.
Stable test attributes
Visibility teeth. Each attribute must be effectively visible when active.
| data-test | Where | Purpose |
|---|---|---|
ticket-windows-page | Route | Root editor |
ticket-window-row | Table | Access type row |
ticket-capacity-stepper | Row editor | Capacity |
ticket-claimed-count | Row | Claimed inventory |
ticket-availability-range | Row editor | Start/end window |
ticket-window-save-cta | Editor | Save action |
ticket-window-archive-cta | Row actions | Archive/close |
ticket-window-delete-cta | Row actions | Delete unused type |
ticket-window-undo-toast | Toast region | Undo destructive action |
ticket-window-conflict-modal | Modal | Conflict state |
ticket-window-validation-error | Editor | Inline validation |
ticket-window-messaging-gap | Page | Downstream messaging gap |
Agent test plan
- ticket-windows-renders
- save-capacity-window
- close-window
- permission-denied-boundary
- cross-tenant-404
- soft-delete-audit
- archive-delete-distinction
- publish-edit-lock
- audit-row-every-change
- concurrent-organizers-conflict
- destructive-undo-window
- capacity-below-claimed
- timezone-window
- downstream-messaging-gap