package domain import ( "errors" "time" "github.com/google/uuid" ) type RSVPResponse string const ( RSVPAttending RSVPResponse = "attending" RSVPDeclined RSVPResponse = "declined" RSVPMaybe RSVPResponse = "maybe" ) func (r RSVPResponse) Valid() bool { switch r { case RSVPAttending, RSVPDeclined, RSVPMaybe: return true } return false } type RSVP struct { ID uuid.UUID `json:"id"` GuestID uuid.UUID `json:"guest_id"` Response RSVPResponse `json:"response"` PlusOnes int `json:"plus_ones"` DietaryNotes *string `json:"dietary_notes,omitempty"` SubmittedAt time.Time `json:"submitted_at"` DeviceFingerprint map[string]any `json:"device_fingerprint,omitempty"` IPAddress *string `json:"ip_address,omitempty"` RiskScore *int `json:"risk_score,omitempty"` EditCount int `json:"edit_count"` } // RSVPRevision is one snapshot of an RSVP's previous state, written before // the new values are applied on PATCH /rsvp/{token}. The host history view // renders these newest-first so the edit trail is auditable. type RSVPRevision struct { ID uuid.UUID `json:"id"` RSVPID uuid.UUID `json:"rsvp_id"` PrevResponse RSVPResponse `json:"prev_response"` PrevPlusOnes int `json:"prev_plus_ones"` PrevDietary *string `json:"prev_dietary,omitempty"` ChangedAt time.Time `json:"changed_at"` } // MaxRSVPEdits caps the number of times a single RSVP can be revised. // The 6th attempt returns 429 — keeps a hostile actor from churning the // host's activity feed with endless updates. const MaxRSVPEdits = 5 var ( ErrRSVPAlreadySubmitted = errors.New("rsvp already submitted") ErrRSVPBlocked = errors.New("rsvp blocked due to fraud risk") ErrRSVPNotFound = errors.New("rsvp not found") ErrRSVPEditLimitReached = errors.New("rsvp edit limit reached") )