Spec, research decisions, implementation plan, data model, API contract, and task breakdown for the RSVP feature. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
11 KiB
Tasks: RSVP to an Event
Input: Design documents from /specs/008-rsvp/
Prerequisites: plan.md, spec.md, data-model.md, contracts/create-rsvp.yaml, research.md, quickstart.md
Tests: Included — constitution mandates Test-Driven Methodology (tests before implementation).
Organization: Tasks grouped by user story for independent implementation and testing.
Format: [ID] [P?] [Story] Description
- [P]: Can run in parallel (different files, no dependencies)
- [Story]: Which user story this task belongs to (e.g., US1, US2)
- Exact file paths included in descriptions
Phase 1: Setup
Purpose: OpenAPI spec and database migration — shared infrastructure for all user stories
- T001 Update OpenAPI spec with RSVP endpoint, request/response schemas, and
attendeeCountpopulation inbackend/src/main/resources/openapi/api.yaml - T002 [P] Create Liquibase migration for rsvps table in
backend/src/main/resources/db/changelog/003-create-rsvps-table.xml - T003 [P] Include new migration in
backend/src/main/resources/db/changelog/db.changelog-master.xml
Phase 2: Foundational (Blocking Prerequisites)
Purpose: Token value objects and cross-cutting refactoring — MUST complete before user stories
Why blocking: All new RSVP code uses typed tokens. Existing code must be refactored first to avoid mixing raw UUID and typed tokens.
- T004 [P] Create
EventTokenrecord inbackend/src/main/java/de/fete/domain/model/EventToken.java - T005 [P] Create
OrganizerTokenrecord inbackend/src/main/java/de/fete/domain/model/OrganizerToken.java - T006 [P] Create
RsvpTokenrecord inbackend/src/main/java/de/fete/domain/model/RsvpToken.java - T007 Refactor
Eventdomain model to useEventToken/OrganizerTokeninbackend/src/main/java/de/fete/domain/model/Event.java - T008 Refactor
EventRepositoryport to use typed tokens inbackend/src/main/java/de/fete/domain/port/out/EventRepository.java - T009 Refactor
EventPersistenceAdapterto map typed tokens inbackend/src/main/java/de/fete/adapter/out/persistence/EventPersistenceAdapter.java - T010 Refactor
EventServiceto use typed tokens inbackend/src/main/java/de/fete/application/service/EventService.java - T011 Refactor
EventControllerto unwrap/wrap typed tokens at API boundary inbackend/src/main/java/de/fete/adapter/in/web/EventController.java - T012 Update
EventServiceTestto use typed tokens inbackend/src/test/java/de/fete/application/service/EventServiceTest.java - T013 Update
EventControllerIntegrationTestto use typed tokens inbackend/src/test/java/de/fete/adapter/in/web/EventControllerIntegrationTest.java - T014 Verify all existing tests pass after token refactoring (
cd backend && ./mvnw test)
Checkpoint: All existing tests green with typed tokens. New RSVP domain work can begin.
Phase 3: User Story 1 — Submit an RSVP (Priority: P1) MVP
Goal: A guest can open an active event page, tap the RSVP CTA, enter their name, submit, and see confirmation. Server persists the RSVP and returns an rsvpToken. localStorage stores RSVP data. Attendee count is populated from real data.
Independent Test: Open an event page, submit an RSVP with a name, verify attendee count updates, verify localStorage contains rsvpToken and name.
Backend Tests for US1
- T015 [P] [US1] Write unit tests for
RsvpService(create RSVP, validation, event-not-found) inbackend/src/test/java/de/fete/application/service/RsvpServiceTest.java - T016 [P] [US1] Write integration tests for
POST /events/{eventToken}/rsvps(201 success, 400 validation, 404 not found) inbackend/src/test/java/de/fete/adapter/in/web/EventControllerIntegrationTest.java
Backend Implementation for US1
- T017 [P] [US1] Create
Rsvpdomain entity inbackend/src/main/java/de/fete/domain/model/Rsvp.java - T018 [P] [US1] Create
CreateRsvpUseCaseinbound port inbackend/src/main/java/de/fete/domain/port/in/CreateRsvpUseCase.java - T019 [P] [US1] Create
RsvpRepositoryoutbound port withsave()andcountByEventId()inbackend/src/main/java/de/fete/domain/port/out/RsvpRepository.java - T020 [P] [US1] Create
RsvpJpaEntityinbackend/src/main/java/de/fete/adapter/out/persistence/RsvpJpaEntity.java - T021 [P] [US1] Create
RsvpJpaRepository(Spring Data) inbackend/src/main/java/de/fete/adapter/out/persistence/RsvpJpaRepository.java - T022 [US1] Implement
RsvpPersistenceAdapterinbackend/src/main/java/de/fete/adapter/out/persistence/RsvpPersistenceAdapter.java - T023 [US1] Implement
RsvpService(create RSVP logic, validate event exists) inbackend/src/main/java/de/fete/application/service/RsvpService.java - T024 [US1] Add
createRsvp()method toEventControllerinbackend/src/main/java/de/fete/adapter/in/web/EventController.java - T025 [US1] Wire attendee count: add
countByEventId()call to GET event flow, populateattendeeCountin response inbackend/src/main/java/de/fete/adapter/in/web/EventController.java - T026 [US1] Verify backend tests pass (
cd backend && ./mvnw test)
Frontend Tests for US1
- T027 [P] [US1] Write unit tests for
BottomSheetcomponent infrontend/src/components/__tests__/BottomSheet.spec.ts - T028 [P] [US1] Write unit tests for
RsvpBarcomponent infrontend/src/components/__tests__/RsvpBar.spec.ts - T029 [P] [US1] Update unit tests for
useEventStoragecomposable (rsvpToken/rsvpName fields) infrontend/src/composables/__tests__/useEventStorage.spec.ts
Frontend Implementation for US1
- T030 [US1] Regenerate TypeScript types from updated OpenAPI spec (
frontend/src/api/schema.d.ts) - T031 [P] [US1] Extend
useEventStoragecomposable withrsvpTokenandrsvpNamefields infrontend/src/composables/useEventStorage.ts - T032 [P] [US1] Create
BottomSheet.vuecomponent (slide-up, backdrop, focus trap, ESC close, aria-modal) infrontend/src/components/BottomSheet.vue - T033 [P] [US1] Create
RsvpBar.vuesticky bottom bar (CTA state + status state) infrontend/src/components/RsvpBar.vue - T034 [US1] Integrate
RsvpBar+BottomSheet+ RSVP form intoEventDetailView, including error state when server is unreachable, infrontend/src/views/EventDetailView.vue - T035 [US1] Add bottom sheet and sticky bar styles to
frontend/src/assets/main.css - T036 [US1] Update
EventDetailViewunit tests for RSVP integration infrontend/src/views/__tests__/EventDetailView.spec.ts
E2E Tests for US1
- T037 [US1] Write E2E tests: RSVP submission flow, localStorage verification, attendee count update in
frontend/e2e/event-rsvp.spec.ts
Checkpoint: US1 complete — guest can submit RSVP, see confirmation, attendee count populated. All backend + frontend tests green.
Phase 4: User Story 2 — RSVP Blocked on Expired Events (Priority: P2)
Goal: Expired events hide the RSVP form and the server rejects RSVP submissions with 409 Conflict.
Independent Test: Attempt to RSVP to an expired event — verify form is hidden client-side and server returns 409.
Tests for US2
- T038 [P] [US2] Write backend test for expired event rejection (409) in
backend/src/test/java/de/fete/application/service/RsvpServiceTest.java - T039 [P] [US2] Write integration test for
POST /events/{eventToken}/rsvpsreturning 409 on expired event inbackend/src/test/java/de/fete/adapter/in/web/EventControllerIntegrationTest.java
Implementation for US2
- T040 [US2] Add expiry check to
RsvpService.createRsvp()— throwEventExpiredExceptionwhen event date has passed inbackend/src/main/java/de/fete/application/service/RsvpService.java - T041 [US2] Handle
EventExpiredExceptioninGlobalExceptionHandler— return 409 Conflict inbackend/src/main/java/de/fete/adapter/in/web/GlobalExceptionHandler.java - T042 [US2] Hide RSVP bar/form on expired events in
EventDetailView(checkexpiredfield from API response) infrontend/src/views/EventDetailView.vue - T043 [US2] Write E2E test for expired event: verify RSVP form hidden, direct API call returns 409 in
frontend/e2e/event-rsvp.spec.ts - T044 [US2] Verify all tests pass (
cd backend && ./mvnw test && cd ../frontend && npm run test:unit)
Checkpoint: US2 complete — expired events block RSVPs client-side and server-side.
Phase 5: Polish & Cross-Cutting Concerns
Purpose: Final verification across all stories
- T045 Run full backend verify (
cd backend && ./mvnw verify) - T046 Run frontend build and type-check (
cd frontend && npm run build) - T047 Run all E2E tests (
cd frontend && npx playwright test) - T048 Visual verification of RSVP flow using
browser-interactive-testingskill
Dependencies & Execution Order
Phase Dependencies
- Setup (Phase 1): No dependencies — can start immediately
- Foundational (Phase 2): Depends on T001 (OpenAPI spec) for schema awareness; T002-T003 (migration) independent
- US1 (Phase 3): Depends on Phase 2 completion (typed tokens in place)
- US2 (Phase 4): Depends on Phase 3 (RSVP creation must exist before expiry guard)
- Polish (Phase 5): Depends on all user stories complete
User Story Dependencies
- US1 (P1): Can start after Phase 2 — no dependency on US2
- US2 (P2): Depends on US1 (the RSVP endpoint and form must exist before adding the expiry guard)
Within Each User Story
- Tests MUST be written first and FAIL before implementation
- Domain model/ports before persistence adapters
- Persistence before services
- Services before controllers
- Backend before frontend (API must exist for frontend to consume)
- Frontend components before view integration
- Unit tests before E2E tests
Parallel Opportunities
Phase 1: T002 and T003 can run in parallel with T001 Phase 2: T004, T005, T006 in parallel; then T007-T013 sequentially (refactoring chain) Phase 3 Backend: T015+T016 (tests) in parallel; T017+T018+T019+T020+T021 (domain/ports/JPA) in parallel; then T022→T023→T024→T025 sequential Phase 3 Frontend: T027+T028+T029 (tests) in parallel; T031+T032+T033 in parallel; then T034→T035→T036→T037 sequential Phase 4: T038+T039 (tests) in parallel; then T040→T041→T042→T043→T044 sequential
Implementation Strategy
MVP First (User Story 1 Only)
- Complete Phase 1: Setup (OpenAPI + migration)
- Complete Phase 2: Foundational (token value objects + refactoring)
- Complete Phase 3: User Story 1 (full RSVP flow)
- STOP and VALIDATE: Guest can submit RSVP, see confirmation, attendee count works
- Deploy/demo if ready
Incremental Delivery
- Setup + Foundational → Token refactoring complete, schema ready
- Add US1 → Full RSVP flow works → Deploy/Demo (MVP!)
- Add US2 → Expired events guarded → Deploy/Demo
- Polish → All tests green, visual verification done
Notes
- Cancelled event guard (FR-010) is deferred until US-18 — NOT included in tasks
- No CAPTCHA/rate-limiting per spec (KISS, privacy-first)
- RSVP editing/withdrawal deferred to separate edit-RSVP spec
- Frontend uses plain
stringfor tokens (no branded types) per clarification - Backend uses typed records (
EventToken,OrganizerToken,RsvpToken) per clarification