Files
Kwaku Danso 39533162bb feat(tier2): editable RSVPs — Block A
Guests can revisit their invitation link and change their response
or plus-ones up to 5 times. Each prior state is snapshotted into
`rsvp_revisions` and surfaced to the host via a per-guest history
modal on the event detail page.

- Migration 0007 adds rsvp_revisions + rsvps.edit_count (with down)
- RSVPRepo.Update wraps snapshot+update+counter in one transaction,
  FOR UPDATE-locking the row so concurrent edits can't bypass the cap
- PATCH /rsvp/{token} re-runs the fraud check on every edit attempt
  (different device on an edit is itself a signal)
- POST /rsvp no longer marks the token used — the link stays valid
  so the guest can come back to edit
- GET /access/{token} now embeds the existing RSVP so the frontend
  renders an edit form instead of a blank submit form on revisit
- New host endpoint GET /events/{id}/guests/{guest_id}/rsvp/history
- Frontend: rsvp/[token].vue toggles between summary + edit form,
  surfaces edits-remaining; dashboard adds a "History" action on
  responded guests opening a revision-trail modal

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-17 19:27:50 +01:00

26 lines
1.0 KiB
SQL
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
-- Tier 2 Block A — editable RSVPs.
--
-- Guests can revisit their invitation link after submitting and change their
-- response or plus-one count. Every prior state is captured in rsvp_revisions
-- so the host can see the trail of edits.
--
-- The plan called this 0004_rsvp_edits in TIER2_PLAN.md; using the next free
-- slot (0007) because 00040006 were taken by Tier 1 work.
CREATE TABLE IF NOT EXISTS rsvp_revisions (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
rsvp_id UUID NOT NULL REFERENCES rsvps(id) ON DELETE CASCADE,
prev_response rsvp_response NOT NULL,
prev_plus_ones INTEGER NOT NULL,
prev_dietary TEXT,
changed_at TIMESTAMPTZ NOT NULL DEFAULT now()
);
CREATE INDEX IF NOT EXISTS idx_rsvp_revisions_rsvp
ON rsvp_revisions(rsvp_id, changed_at DESC);
-- Hard cap on how many times a guest can edit. The numeric cap (5) is
-- enforced in Go; storing the running count avoids a count(*) on every PATCH.
ALTER TABLE rsvps
ADD COLUMN IF NOT EXISTS edit_count SMALLINT NOT NULL DEFAULT 0;