# Group Messaging ## What ships today (NIP-17 group DMs) SkateSpots group chat uses the **NIP-17 fan-out primitive** — the same encryption path as 1:1 DMs, just addressed to more than one person: - The sender builds one **kind-14 rumor** with a `p` tag per recipient, then encrypts that same rumor **to each recipient separately** inside a kind-13 seal, wrapped in a kind-1059 gift wrap addressed only to them. - Anyone receiving a rumor with **more than one `p` tag** is in a group. - A group is identified by `getGroupId(participants)` — the sorted, joined participant pubkeys — so every client derives the same id. Implementation: | Piece | File | | --- | --- | | Send (1:1 or group) | `useDirectMessages.ts` → `useSendDirectMessage` (`createRumor`) | | List groups (inbox) | `useDirectMessages.ts` → `useGroupConversations` | | Group thread | `useDirectMessages.ts` → `useGroupConversation(participants)` | | Thread UI | `pages/GroupConversationPage.tsx` → `/messages/group/:participants` | | Create a group | `components/NewMessageDialog.tsx` (multi-select → *Start group*) | ## Honest limitations This primitive is simple and interoperable, but it is **not** a modern group protocol: - **No forward secrecy / post-compromise security.** One leaked message key can expose that message (and, with a leaked identity key, the whole history). - **No membership ratchet or roster.** "Membership" is just whoever is in the `p` tags; there is no cryptographic join/leave, and no automatic rekey when someone is removed. - **Fan-out cost** is O(n) per message (one sealed copy per recipient). - **Metadata** (timing, group size) is visible to relays. Good enough for casual crew/community chats. Not appropriate for high-stakes or large public rooms. ## Upgrade paths (when the guarantees matter) From *Encrypted Group Chat on Nostr: Marmot, Concord, and Cordn Compared* (): | Protocol | Crypto | Use when | | --- | --- | --- | | **Marmot** | MLS (RFC 9420), no privileged server | Small, high-stakes groups needing forward secrecy + post-compromise security; the most mature spec and a flagship Rust implementation (MDK) | | **Concord** | Shared key + NIP-59 giftwrap, signed roster | Large, public, Discord-style communities (channels/roles/moderation). Trades forward secrecy for scale | | **Cordn** | MLS via a per-group coordinator (ContextVM) | MLS guarantees where running/finding a small self-hostable coordinator is acceptable; best public-metadata story | Migration would be additive: keep the NIP-17 threads for casual DMs and adopt one of the above for rooms that need ratcheting, rosters and moderation. Revisit when the target protocol's spec has stabilised. ## Decision Ship NIP-17 group DMs now (zero new protocols, reuses the DM stack); adopt **Marmot** if/when teams need Signal-grade guarantees, and **Concord** if the goal becomes large public communities. See the article above for the trade-offs.