Files
fete/specs/024-cancel-event/spec.md
nitrix 6aeb4b8bca Migrate project artifacts to spec-kit format
- Move cross-cutting docs (personas, design system, implementation phases,
  Ideen.md) to .specify/memory/
- Move cross-cutting research and plans to .specify/memory/research/ and
  .specify/memory/plans/
- Extract 5 setup tasks from spec/setup-tasks.md into individual
  specs/001-005/spec.md files with spec-kit template format
- Extract 20 user stories from spec/userstories.md into individual
  specs/006-026/spec.md files with spec-kit template format
- Relocate feature-specific research and plan docs into specs/[feature]/
- Add spec-kit constitution, templates, scripts, and slash commands
- Slim down CLAUDE.md to Claude-Code-specific config, delegate principles
  to .specify/memory/constitution.md
- Update ralph.sh with stream-json output and per-iteration logging
- Delete old spec/ and docs/agents/ directories
- Gitignore Ralph iteration JSONL logs

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-06 20:19:41 +01:00

8.2 KiB

Feature Specification: Cancel an Event as Organizer

Feature: 024-cancel-event Created: 2026-03-06 Status: Draft Source: Migrated from spec/userstories.md

User Scenarios & Testing

User Story 1 - Cancel event with optional message (Priority: P1)

The event organizer, from the organizer view, triggers a dedicated "Cancel event" action. A confirmation step is required before finalising. The organizer may optionally enter a cancellation message (reason or explanation). After confirmation, the server sets the event to cancelled state with the provided message. The event page immediately displays a "cancelled" state visible to all visitors. No RSVP submissions are accepted by the server from this point.

Why this priority: Cancellation is a fundamental lifecycle action — guests need to be clearly informed when an event is cancelled rather than discovering it silently. This is the core of US-18.

Independent Test: Can be fully tested by creating an event, triggering cancel (with and without a message), and verifying the event page shows a "cancelled" indicator and the RSVP form is absent.

Acceptance Scenarios:

  1. Given an organizer with a valid organizer token in localStorage, When they click "Cancel event", Then a confirmation step is shown before any change is made.
  2. Given the organizer confirms cancellation without entering a message, When the server processes the request, Then the event is marked cancelled and the event page shows a "cancelled" state with no message.
  3. Given the organizer confirms cancellation with a message, When the server processes the request, Then the event page displays the "cancelled" state along with the cancellation message.
  4. Given a cancelled event, When a guest attempts to submit an RSVP, Then the server rejects the submission and the RSVP form is not shown on the event page.
  5. Given a cancelled event that has not yet expired, When any visitor opens the event URL, Then the full event page renders with a clear "cancelled" indicator — no partial data is hidden.

User Story 2 - Adjust expiry date during cancellation (Priority: P2)

When cancelling, the organizer can optionally adjust the event's expiry date to control how long the cancellation notice remains visible before automatic data deletion (US-12). The adjusted date must be in the future, consistent with US-5's expiry date constraint.

Why this priority: The expiry date adjustment is a convenience — organizers may want to keep the cancellation notice visible for a specific period (e.g. one more week) or trigger earlier cleanup. The core cancellation (P1) works without it.

Independent Test: Can be tested by cancelling an event while setting a new expiry date in the future, then verifying the event's expiry date was updated and data persists until that date.

Acceptance Scenarios:

  1. Given the organizer confirms cancellation with a new expiry date set in the future, When the server processes the request, Then the event is cancelled and its expiry date is updated to the provided value.
  2. Given the organizer provides an expiry date in the past or set to today during cancellation, When the server processes the request, Then the request is rejected with a clear validation error.
  3. Given the organizer confirms cancellation without adjusting the expiry date, When the server processes the request, Then the existing expiry date is unchanged.

User Story 3 - Edit cancellation message after cancellation (Priority: P3)

After an event is cancelled, the organizer can update the cancellation message (e.g. to correct a typo or add further explanation). The cancelled state itself cannot be changed.

Why this priority: Editing the message is a refinement capability. The core behaviour (cancellation + message at time of cancellation) is sufficient for P1 and P2.

Independent Test: Can be tested by cancelling an event, then submitting an updated cancellation message via the organizer view, and verifying the new message is displayed on the event page.

Acceptance Scenarios:

  1. Given a cancelled event with a valid organizer token, When the organizer submits an updated cancellation message, Then the event page displays the new message.
  2. Given a cancelled event with a valid organizer token, When the organizer attempts to un-cancel (set the event back to active), Then the server rejects the request — cancellation is a one-way state transition.
  3. Given a cancelled event with an absent or invalid organizer token, When a request is made to edit the cancellation message, Then the server rejects the request.

Edge Cases

  • Organizer token absent or invalid: the "Cancel event" action is not shown in the UI and the server rejects any cancel or message-edit request with an appropriate error response.
  • RSVP on a cancelled event: the server rejects RSVP submissions with a clear error; the RSVP form is hidden on the client.
  • Cancellation message is optional: omitting it is valid — the event still transitions to cancelled state with no message displayed.
  • Cancellation + expiry: after the expiry date passes, the event is deleted by the cleanup process (US-12) regardless of cancelled state; the cancellation data is removed as part of the full event deletion.
  • Already-expired event at time of cancellation: [NEEDS EXPANSION] — it is unclear whether cancellation should be allowed if the event has already expired but not yet been cleaned up. This edge case should be addressed during implementation.

Requirements

Functional Requirements

  • FR-001: The Event entity MUST persist a is_cancelled boolean (default false) and an optional cancellation_message string, both server-side.
  • FR-002: The cancel endpoint MUST require a valid organizer token; requests without a valid token are rejected.
  • FR-003: The cancel endpoint MUST accept an optional plain-text cancellation message.
  • FR-004: The cancel endpoint MUST accept an optional updated expiry date, which MUST be in the future; if provided and not in the future, the request is rejected with a clear validation error.
  • FR-005: Cancellation MUST be a one-way state transition: once cancelled, the event cannot be set back to active via any API endpoint.
  • FR-006: The event page MUST display a "cancelled" state indicator and the cancellation message (if present) for any visitor once the event is cancelled.
  • FR-007: The RSVP endpoint MUST reject submissions for cancelled events; the RSVP form MUST be hidden on the client for cancelled events.
  • FR-008: The organizer MUST be able to update the cancellation message after cancellation via a dedicated update action; this action MUST require a valid organizer token.
  • FR-009: The UI MUST present a confirmation step before submitting the cancellation request; the cancel action MUST NOT be triggerable in a single click without confirmation.
  • FR-010: The "Cancel event" action and organizer-specific cancel UI MUST NOT be rendered when no valid organizer token is present in localStorage.
  • FR-011: No personal data, IP addresses, or identifiers MUST be logged during cancellation or cancellation message updates.

Key Entities

  • CancellationState: Value type on Event. Fields: is_cancelled (boolean, persistent), cancellation_message (optional string, persistent). Not a separate entity — stored on the Event record.

Success Criteria

Measurable Outcomes

  • SC-001: An organizer with a valid token can cancel an event (with or without a message) in a single confirmed action, and the cancelled state is immediately reflected on the event page.
  • SC-002: After cancellation, no guest can successfully submit an RSVP via the API, regardless of client-side state.
  • SC-003: The event page correctly renders a "cancelled" indicator (and message if provided) for any visitor after cancellation — no RSVP form, no false "active" state.
  • SC-004: Cancellation data (state and message) is removed automatically when the event expires and is deleted by the cleanup process (US-12).
  • SC-005: No client or API call can revert a cancelled event to an active state.