W011: Decline invitation
Marks a pending invitation as declined. Triggered from My Invitations by an authenticated user who received the invitation and chooses not to accept. Operates on the invitation id, not the token (the user has already authenticated, so they can be matched by email rather than by an opaque link).
Steps
-
Decline by id and caller email. Call
Platform.declineInvitation(invitationId, callerEmail). The L2 op setsrevoked_at = NOW()if and only if the invitation id matches, the caller's email matches the invitation's email (case-insensitive), and the invitation is still pending. Returns whether a row was updated. -
Map to a typed result. If the L2 op returned false, raise
NotFoundError(covers both "no such invitation" and "already consumed").
Returns
{ ok: true } on success.
Business rules
- Authenticated, not token-based. Unlike Accept (W011), Decline is only callable by someone who has logged in and whose email matches the invitation.
- Shared storage with Revoke. Decline and Revoke (W010) both write
revoked_at; there is no separatedeclined_atcolumn. The distinction is preserved at the call boundary (who triggered it), not in the data. - No undo. A declined invitation cannot be restored; the admin must send a new one.
Errors
NotFoundError. The invitation does not exist, or the caller's email does not match it, or the invitation is already accepted or revoked.