mirror of
https://github.com/element-hq/matrix-authentication-service.git
synced 2026-10-12 22:18:26 +00:00
Mints a single-use, passwordless registration token for each guest, pinned to their address and username and expiring after `guest_invites.invite_lifetime`, and schedules their invite emails. The links are only ever mailed to the guests, so the response carries a count rather than the tokens. Everything is validated before anything is minted, and the batch is committed as a whole, so a rejected request sends no email at all. Each invite goes through the registration policy as `POST /register` will check it, so an invite the guest form would refuse is a 400 naming the invite and every violation. The policy sees an empty requester, as the request comes from the inviter's homeserver rather than the guest. A username that is already taken is refused up front, rather than emailed out as a link nobody can register with. Addresses are deduplicated ignoring case before the usernames are checked, keeping the first entry, so a repeated address never counts as a username given twice. The caller sends the room name and the inviter on the inviter's behalf, so the endpoint doesn't trust them. The room name and the inviter's display name are stripped of control characters, including the bidirectional controls `char::is_control` misses, and truncated before they are stored in the job payload. The inviter's Matrix ID is never truncated, so it can't show a server it isn't from: it is kept whole if it is valid under the historical grammar, and left out otherwise. The room ID is checked as `/open-room` checks it, and is only recorded on the span once it is valid. The endpoint answers 404 while guest invites are disabled. The check is in the handler, as the admin router doesn't see the configuration. `guest_invites.enabled` turns it on, and requires `client_room_url`. `/open-room` keeps using `client_room_url` while the endpoint is disabled, so that links already sent keep working. `invite_lifetime` is a positive number of seconds that fits in a `u32`, so MAS refuses a zero or negative lifetime at startup, and adding it to the current time can't overflow. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>