Expand description
Public (link) invites (GROUP_PROTOCOL.md).
A public invite is a shareable URL — https://vectorapp.io/invite#<fragment> — whose
#fragment carries a fetch-token, never the keys directly. The token decrypts a
bundle posted on the community’s relays. This indirection (token → relay bundle) is
what buys Discord-style rotate/revoke/expire without changing the URL.
From the token, three sub-keys derive (super::derive):
- a NIP-44 decryption key for the bundle content;
- a locator (the addressable
d-tag) so the bundle is findable on relays; - a stable signer key, so re-posting under one coordinate rotates the link and a joiner can reject an impostor bundle squatting the locator.
The bundle carries the same join material a private invite does (CommunityInvite)
plus a preview (name, description, logo) so a recipient sees what they’re joining
before committing. The preview lives inside the token-gated ciphertext, so a relay
scraper without the link sees only an opaque blob — metadata privacy holds.
Structs§
- Public
Invite Bundle - The full decrypted bundle: a preview + the join material + an optional expiry + attribution.
- Public
Invite Preview - The non-secret community details shown before joining (no member count — the protocol hides membership, so any count would be a fiction).
Enums§
- Public
Invite Error - Errors building or parsing a public invite.
Constants§
- INVITE_
URL_ BASE - Default invite URL base. The path is irrelevant to the protocol (the fragment is read client-side and never sent to the server); only the fragment matters.
Functions§
- build_
public_ invite_ event - Build the signed, token-encrypted bundle event to post on the community’s relays.
Addressable (kind 30078) at coordinate
(30078, signer(token), d=locator(token))so re-posting under the same token replaces it (rotate); deleting it revokes the link. - build_
public_ invite_ tombstone - Build a token-signed TOMBSTONE at the bundle’s coordinate: an empty-content replaceable event with a
fresh
created_atthat REPLACES the live bundle. Relays honor replaceable-event replacement far more reliably than NIP-09a-tag (coordinate) deletions of addressable events — so publishing this on revoke, alongside the deletion, guarantees the bundle is overwritten (the browser preview dies) even on relays that silently ignore coordinate deletions. The empty content fails to decrypt to a valid bundle, so a fetcher gets nothing. - encode_
invite_ url - Build the shareable invite URL (v2 binary fragment):
[ver][flags][relays?][token:32], base64url. The stock relay set costs zero bytes (flag bit); known relays cost one byte each (dictionary); customs are length-prefixed literals withwss://implied. ~74 chars total in the common case, vs ~269 for the v1 JSON fragment it replaces. - locator_
hex - The addressable
d-tag (hex locator) a public invite fortokenis posted under — the value to query relays by. - new_
token - Mint a fresh 32-byte token (OsRng). The whole secret of a public invite.
- parse_
invite_ url - Parse a shareable invite URL (or a bare fragment) back to
(relays, token). Accepts the full URL or just the fragment after#, in either the v2 binary format or the legacy v1 JSON format (v1 links in the wild stay valid forever). - parse_
public_ invite_ event - Verify + decrypt a bundle event with the URL token. Checks: protocol version (before
decrypt), sub-kind, that the author is the token-derived signer (rejects an impostor
squatting the locator), the signature, then decrypts under the token key. Does NOT
enforce expiry (so a preview can still render an expired link); callers gate joins on
PublicInviteBundle::is_expired. - signer_
pubkey - The public key a valid bundle for
tokenmust be signed by.