# Implementation Plan: Cancel Event **Branch**: `016-cancel-event` | **Date**: 2026-03-12 | **Spec**: [spec.md](spec.md) **Input**: Feature specification from `/specs/016-cancel-event/spec.md` ## Summary Allow organizers to permanently cancel events via a bottom sheet UI. Cancelled events display a red banner to visitors and block new RSVPs. Implementation adds a `PATCH /events/{eventToken}` endpoint, extends the Event entity with `cancelled` and `cancellationReason` fields, and reuses the existing `BottomSheet.vue` component for the cancel interaction. ## Technical Context **Language/Version**: Java 25 (backend), TypeScript 5.9 (frontend) **Primary Dependencies**: Spring Boot 3.5.x, Vue 3, Vue Router 5, openapi-fetch, openapi-typescript **Storage**: PostgreSQL (JPA via Spring Data, Liquibase migrations) **Testing**: JUnit (backend), Vitest (frontend unit), Playwright + MSW (frontend E2E) **Target Platform**: Self-hosted Linux server, mobile-first PWA **Project Type**: Web application (REST API + SPA) **Performance Goals**: N/A — simple state transition, no performance-critical path **Constraints**: Privacy by design (no analytics/tracking), WCAG AA, mobile-first **Scale/Scope**: Single new endpoint, 2 new DB columns, 1 view extension ## Constitution Check *GATE: Must pass before Phase 0 research. Re-check after Phase 1 design.* | Principle | Status | Notes | |-----------|--------|-------| | I. Privacy by Design | PASS | No new data collection beyond organizer-provided reason. No analytics. | | II. Test-Driven Methodology | PASS | TDD enforced: tests before implementation, E2E mandatory for both user stories. | | III. API-First Development | PASS | OpenAPI spec updated first, types generated before implementation. `example:` fields included. | | IV. Simplicity & Quality | PASS | Minimal change: 2 columns, 1 endpoint, reuse existing BottomSheet. No over-engineering. | | V. Dependency Discipline | PASS | No new dependencies required. | | VI. Accessibility | PASS | Reuses accessible BottomSheet component. Banner uses semantic HTML + ARIA. | **Gate result: PASS** — no violations. ## Project Structure ### Documentation (this feature) ```text specs/016-cancel-event/ ├── plan.md # This file ├── spec.md # Feature specification ├── research.md # Phase 0 output — design decisions ├── data-model.md # Phase 1 output — entity changes ├── quickstart.md # Phase 1 output — implementation overview ├── contracts/ # Phase 1 output — API contract additions │ └── patch-event-endpoint.yaml └── tasks.md # Phase 2 output (/speckit.tasks command) ``` ### Source Code (repository root) ```text backend/ ├── src/main/java/de/fete/ │ ├── domain/model/Event.java # + cancelled, cancellationReason, cancel() │ ├── application/service/EventService.java # + CancelEventUseCase implementation │ ├── adapter/in/web/EventController.java # + cancelEvent endpoint │ └── adapter/out/persistence/ │ ├── EventJpaEntity.java # + cancelled, cancellation_reason columns │ └── EventPersistenceAdapter.java # + mapper updates ├── src/main/resources/ │ ├── openapi/api.yaml # + cancel endpoint, request/response schemas │ └── db/changelog/004-add-cancellation-columns.xml # New migration └── src/test/java/de/fete/ # Unit + integration tests frontend/ ├── src/ │ └── views/EventDetailView.vue # + cancel button, bottom sheet, banner └── e2e/ # E2E tests for both user stories ``` **Structure Decision**: Web application (Option 2) — matches existing project layout with `backend/` and `frontend/` at repository root. ## Complexity Tracking > No violations — table not applicable.