Invite codes and the private alpha

Pigeon is invite-only while it's in alpha. An invite code is a single-use ticket in, and nothing more: it doesn't start a chat, make you anyone's contact, or tell the server who invited you.

What a code does Built

Redeeming a code lets you create one account. You then go through the normal sign-up: a name, your seed phrase, and an empty trusted circle. No contact, chat, request or message is created between you and the person who invited you.

The code Built

  • 219 bytes, shown as pigeon-invite: followed by base32, as a link, or as a QR code. It's made to be pasted, opened or scanned, not typed.
  • It contains no name, handle, label or account id.
  • Each code is signed with its own key, so only the inviter's own devices can recognise it in their list.
  • It works once. Cancelling a code uses it up. A redemption that fails halfway can be retried safely.
  • The inviter picks how long it lasts: 24 hours, 7 days (the default) or 30 days.

The chosen expiry is enforced by the app. The server's own limit is coarser: codes are tied to weekly keys and it keeps five of them, so no code lives past about 30 days.

Limits Built

  • Only people already in the alpha can make codes, up to 10 a week each (a starting value).
  • An accepted code admits one registration within 14 days.
  • The alpha has an overall cap on accounts.

What the server keeps

Codes are built on blind tokens (the RFC 9497 VOPRF, ristretto255-SHA512, the same family as Pigeon's media tokens). The server signs a code without seeing it, so later it can't match the code it signed to the code being used.

It keeps a list of alpha members, a count of codes each account made this week, and hashes of used codes. Nothing it keeps joins the person who made a code to the code, or a code to the account it created; two tests check exactly that.

What isn't hidden: the network address and the timing of each request. “The server can't tell who invited whom” is true of what it stores; for the network side it's a promise. An independent relay to close that is Planned.

By design there's no “used” state in the inviter's list, only issued, expired or cancelled, so even the inviter isn't told who joined with their code.

What's built and what isn't

  • The invite format, the server's routes, and entering a code when you first open the desktop app Built.
  • Making and cancelling codes from the desktop app, and an inviter's list kept in step across their devices Planned. The screens exist and say so.
  • Mailbox servers refusing accounts outside the alpha Planned: the server records members, but nothing enforces it yet.

Sources: docs/specs/invite-v1.md (sections 1 to 9), ADR-0014 amendment 2 (the private alpha), crates/pigeon-core/src/invite/.

Related: download the alpha, handles and lookups.