Files
fete/specs/014-cancel-rsvp/plan.md
nitrix 41bb17d5c9
All checks were successful
CI / backend-test (push) Successful in 59s
CI / frontend-test (push) Successful in 24s
CI / frontend-e2e (push) Successful in 1m18s
CI / build-and-publish (push) Has been skipped
Add cancel RSVP feature (backend DELETE endpoint + frontend UI)
Allows guests to cancel their RSVP via a DELETE endpoint using their
guestToken. Frontend shows cancel button in RsvpBar and clears local
storage on success. Includes unit tests, integration tests, and E2E spec.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-12 17:45:37 +01:00

4.7 KiB

Implementation Plan: Cancel RSVP

Branch: 014-cancel-rsvp | Date: 2026-03-09 | Spec: spec.md Input: Feature specification from /specs/014-cancel-rsvp/spec.md

Summary

Allow guests to cancel their RSVP either explicitly from the event detail view (tap-to-reveal pattern on the RSVP bar) or implicitly when removing an RSVP'd event from their event list. The backend provides an idempotent DELETE endpoint; the frontend handles confirmation, API call, localStorage cleanup, and UI state reset.

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 + Mockito (backend unit), MockMvc + Testcontainers (backend integration), Vitest (frontend unit), Playwright + MSW (frontend E2E) Target Platform: Self-hosted PWA (web browser, mobile-first) Project Type: Web application (hexagonal backend + SPA frontend) Performance Goals: Cancel operation < 500ms server-side Constraints: Privacy by design (no analytics), token-based auth (no login), idempotent delete Scale/Scope: Single new endpoint, 3 modified frontend components, 1 new composable method

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 PII stored. Delete operation removes data. No analytics.
II. Test-Driven Methodology PASS Plan includes TDD cycle: tests before implementation. E2E mandatory.
III. API-First Development PASS OpenAPI spec updated first, types generated before implementation.
IV. Simplicity & Quality PASS Minimal changes to existing code. No new abstractions. Idempotent delete is the simplest correct approach.
V. Dependency Discipline PASS No new dependencies required.
VI. Accessibility PASS Interactive elements will use semantic HTML, ARIA, keyboard navigation. Confirm dialog already accessible.

Gate result: ALL PASS — proceed to Phase 0.

Project Structure

Documentation (this feature)

specs/014-cancel-rsvp/
├── plan.md              # This file
├── research.md          # Phase 0 output
├── data-model.md        # Phase 1 output
├── contracts/           # Phase 1 output
│   └── cancel-rsvp.yaml # DELETE endpoint contract
└── tasks.md             # Phase 2 output (by /speckit.tasks)

Source Code (repository root)

backend/
├── src/main/java/de/fete/
│   ├── domain/
│   │   ├── model/Rsvp.java                          # existing (no changes)
│   │   ├── model/RsvpToken.java                     # existing (no changes)
│   │   └── port/
│   │       ├── in/CancelRsvpUseCase.java            # NEW use case port
│   │       └── out/RsvpRepository.java              # MODIFY (add deleteByRsvpToken)
│   ├── application/service/RsvpService.java          # MODIFY (implement cancel)
│   └── adapter/
│       ├── in/web/EventController.java               # MODIFY (add DELETE handler)
│       └── out/persistence/
│           ├── RsvpJpaRepository.java                # MODIFY (add deleteByRsvpToken)
│           └── RsvpPersistenceAdapter.java           # MODIFY (implement delete)
├── src/main/resources/openapi/api.yaml               # MODIFY (add DELETE endpoint)
└── src/test/java/de/fete/
    ├── application/service/RsvpServiceTest.java      # MODIFY (add cancel tests)
    └── adapter/in/web/EventControllerIntegrationTest.java  # MODIFY (add cancel tests)

frontend/
├── src/
│   ├── api/schema.d.ts                               # REGENERATE (from updated OpenAPI)
│   ├── components/
│   │   ├── RsvpBar.vue                               # MODIFY (tap-to-reveal cancel)
│   │   ├── EventList.vue                             # MODIFY (conditional dialog msg)
│   │   └── ConfirmDialog.vue                         # existing (no changes)
│   ├── composables/useEventStorage.ts                # MODIFY (add removeRsvp)
│   └── views/EventDetailView.vue                     # MODIFY (add cancel logic)
└── e2e/
    └── cancel-rsvp.spec.ts                           # NEW (E2E tests)

Structure Decision: Follows existing hexagonal architecture. New use case port + implementation in existing service. Single new endpoint added to existing controller.

Complexity Tracking

No constitution violations — table not needed.