draft optional
This extension gives PsstPsst group conversations a stable identity across membership changes. It builds on NIP-17 and uses the split-key envelope and millisecond timestamp extensions.
Stable group identity
NIP-17 normally identifies a room by the rumor author and its p tags, so a
membership change creates another room. PsstPsst adds an opaque stable ID using an h tag, whose naming follows
NIP-29:
["h", "<group-id>"]
Only the first h tag is used. Its value is 1–256 UTF-8 bytes. Senders SHOULD
generate 32 random bytes and encode them as 64 lowercase hexadecimal
characters. A group ID is an identifier, not a public key.
Group kind 14 and kind 15 rumors and wrapped kind 7 reactions carry the
same h value. Groups do not introduce a shared encryption key. Each rumor is
sealed and gift-wrapped separately for every addressed member and for the
sender. Its p tags remain the delivery audience for that rumor.
Group actions
The first action tag describes a group state change:
["action", "invite", "<target-pubkey>"]
["action", "remove", "<target-pubkey>"]
["action", "rename"]
Targets are 64-character lowercase hexadecimal public keys. A malformed first
action tag invalidates the rumor; later action tags are ignored.
A complete invite rumor, before sealing and gift wrapping, has this form:
{
"id": "<rumor-id>",
"pubkey": "<author-identity-pubkey>",
"created_at": "<unix-timestamp>",
"kind": 14,
"tags": [
["p", "<current-member-pubkey>"],
["p", "<invited-member-pubkey>"],
["h", "<group-id>"],
["ms", "<0..999>"],
["action", "invite", "<invited-member-pubkey>"],
["subject", "<current-group-name>"]
],
"content": ""
}
The rumor is unsigned; its kind 13 seal supplies the identity signature. The
subject tag is optional.
Invite
invite is an empty kind 14 rumor. Its target is the new member. Its p tags
contain the current members other than the author and MUST include the target.
This lets the target initialize the group without earlier history.
Remove and leave
remove is an empty kind 14 rumor. When removing another member, the target
MUST remain in p so it can receive the removal. When the target equals the
author, the action means leave and the target need not appear in p.
Rename
rename is an empty kind 14 rumor with a subject tag. A non-empty trimmed
value sets the group name. A missing, empty, or whitespace-only value clears it.
Names contain at most 80 Unicode code points.
Ordinary kind 14 and kind 15 messages SHOULD include the current subject
(an empty value for an unnamed group), so another device can recover the name
without an earlier rename or initial message. An invite MAY also include it.
Group state
An unknown group is initialized by an ordinary non-empty kind 14 message, a
valid kind 15 file offer, or an invite. Its initial roster is the author plus
the valid p values. No first-message action or earlier history is required.
Reactions, empty ordinary messages, remove, and rename cannot initialize a
group. Legacy exact-shape action=create tags are treated as ordinary content,
not state changes. After initialization, ordinary-message
p tags describe only that rumor’s audience and MUST NOT replace the roster.
Membership actions are applied in rumor order. Their author MUST be a member at
that point in the action history. invite adds its target and remove removes
its target. A later invite may add a removed member again. Any current member
may publish an action; there is no administrator or membership quorum.
Only the first subject tag is used. On any accepted kind 14 or kind 15
group rumor, absence preserves the name, a missing or empty value clears it, and
other values are trimmed. The newest accepted subject under the event order
wins independently of membership replay. An overlong subject is ignored on an
ordinary message or invite; it invalidates a rename action.
This extension does not deliver earlier rumors to a newly invited member.
Private saved groups
Saved-group bookmarks use the shared contacts list described in Private account lists. Saving a group does not change its roster or message encryption.
Compatibility
Stable-group interoperability requires processing h and action in addition
to the split-key envelope.