Skip to main content
Version: v1.0.0(int)

W020: Send invitation

Creates a tokenized invitation for a prospective member and emails them the accept link. Triggered from Settings, Users, Invite. Idempotent on repeat invites to the same pending email.

Steps​

  1. Block invites to existing members. Call Platform.userExistsByEmailInOrg(email, orgId). If true, reject.

  2. Reject owner role. Ownership transfer is a separate (out-of-scope-for-v1) flow.

  3. Short-circuit on existing pending invite. Call Platform.findPendingInvitation(orgId, email). If a pending unexpired invite already exists for this email in this org, re-send the email and return that invite. Skip steps 4 and 5.

  4. Persist the invitation. Call Platform.createInvitation({ orgId, email, role, invitedBy }). The L2 op generates the opaque token and sets expires_at = NOW() + 7 days by DB default.

  5. Send the invitation email. Subject and body include the accept link with the token. Email failure is surfaced to the caller as a warning but does not roll the invitation back; admins can resend later (W009).

Returns​

The created (or pre-existing pending) invitation.

Business rules​

  • Owner or admin only. Authorization is enforced at the request boundary.
  • Re-inviting is idempotent. A second invite for the same email in the same org returns the existing pending invite and re-sends its email. No duplicate row is created.
  • Tokens are opaque, single-use, and expire. The Accept workflow (W011) rejects expired or already-consumed tokens.
  • Owner role is not invitable. Owners are appointed via ownership transfer (future), not invitations.

Errors​

  • ValidationError. The email already belongs to a member of this org, or the requested role is owner.