Files
fete/specs/008-rsvp/data-model.md
nitrix 4828d06aba Add 008-rsvp feature spec and design artifacts
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>
2026-03-08 11:48:00 +01:00

4.4 KiB

Data Model: RSVP to an Event (008)

Date: 2026-03-06

Entities

Rsvp (NEW)

Field Type Required Constraints Notes
id Long yes BIGSERIAL, PK Internal only, never exposed
rsvpToken RsvpToken yes UNIQUE, NOT NULL Server-generated UUID, returned to client
eventId Long yes FK -> events.id, NOT NULL Which event this RSVP belongs to
name String yes 1-100 chars, NOT NULL Guest's display name

Notes:

  • No attending boolean — existence of an entry implies attendance (per spec).
  • No createdAt — not required by the spec. Can be added later if needed (e.g. for guest list sorting in 009).
  • Duplicates from different devices or cleared localStorage are accepted (privacy trade-off).

Token Value Objects (NEW)

Record Field Type Notes
EventToken value UUID Immutable, non-null. Java record wrapping UUID
OrganizerToken value UUID Immutable, non-null. Java record wrapping UUID
RsvpToken value UUID Immutable, non-null. Java record wrapping UUID

Purpose: Type-safe wrappers preventing mix-ups between the three token types at compile time. All generated server-side via UUID.randomUUID(). JPA entities continue to use raw UUID columns — mapping happens in the persistence adapters.

Event (MODIFIED — token fields change type)

The Event domain model's eventToken and organizerToken fields change from raw UUID to their typed record wrappers. No database schema change — the JPA entity keeps raw UUID columns.

Field Old Type New Type
eventToken UUID EventToken
organizerToken UUID OrganizerToken

The attendeeCount was already added to the API response in 007-view-event — it now gets populated from a count query instead of returning 0.

StoredEvent (frontend localStorage — modified)

Field Type Required Notes
eventToken string yes Existing
organizerToken string no Existing (organizer flow)
title string yes Existing
dateTime string yes Existing
expiryDate string yes Existing
rsvpToken string no NEW — set after RSVP submission
rsvpName string no NEW — guest's submitted name

Validation Rules

  • name: required, 1-100 characters, trimmed. Blank or whitespace-only is rejected.
  • rsvpToken: server-generated, never from client input on create.
  • eventId: must reference an existing, non-expired event.

Relationships

Event 1 <---- * Rsvp
  |               |
  eventToken      rsvpToken (unique)
  (public)        (returned to client)

Type Mapping (full stack)

Concept Java PostgreSQL OpenAPI TypeScript
RSVP ID Long bigserial N/A (not exposed) N/A
RSVP Token RsvpToken uuid string uuid string
Event FK Long bigint N/A (path param) N/A
Guest name String varchar(100) string string
Attendee cnt long count(*) integer number

Database Migration

New Liquibase changeset 003-create-rsvps-table.xml:

CREATE TABLE rsvps (
    id          BIGSERIAL PRIMARY KEY,
    rsvp_token  UUID NOT NULL UNIQUE,
    event_id    BIGINT NOT NULL REFERENCES events(id),
    name        VARCHAR(100) NOT NULL
);

CREATE INDEX idx_rsvps_event_id ON rsvps(event_id);
CREATE INDEX idx_rsvps_rsvp_token ON rsvps(rsvp_token);