60 lines
2.9 KiB
Markdown
60 lines
2.9 KiB
Markdown
# 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*
|
|
(<https://nostrdev.com/blog/nostr-group-chat-protocols/>):
|
|
|
|
| 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.
|