Skip to content

Latest commit

 

History

History
147 lines (103 loc) · 7.05 KB

29.md

File metadata and controls

147 lines (103 loc) · 7.05 KB

NIP-29

Simple Group Chat

draft optional author:fiatjaf author:ismyhc depends:33 depends:27 depends:11 depends:42

This NIP defines a model for group chat that relies on relays as ultimate sources of authority. Clients can connect to multiple relays and interact with different groups in each of these relays. A group can live in more than one relay or migrate between relays, but for practical purposes it is expected to rely on a single relay for as long as that is working well. This approach minimizes bandwidth consumption and computation costs and ensures the group can have fine-grained permissions and other niceties commonly expected from any group chat platforms without putting a huge amount of overhead on clients. The fundamental assumption here is that censorship is not a big concern for this kind of application.

Each group has an identifier, which is used as the d tag (see NIP-33) in events that hold group metadata. The default top-level group in a relay is identified by "/", with subgroups added after the slash and even deeper subgroups separated by other slashes. The imagined user flow for opening a group is to type a hostname with an optional path suffix. For example, if the user types pizza.com/ that goes to the top-level group at the wss://pizza.com relay. If the user types pizza.com/flavors that goes to the group "/flavors" on the wss://pizza.com relay.

The entire metadata of the group (kinds 39000-3900x) must only be signed by the relay main pubkey given by the "pubkey" field in the relay's NIP-11 response. Other metadata events not signed by that public key must be ignored by clients. Upon opening a group, the chat client is supposed to fetch (or use locally cached values) these metadata events in order to render the group details, and then fetch the messages (kind:9).

Event definitions

  • chat message (kind:9)

This is the basic unit of a message sent to a group.

It must commit in the g tag to the subgroup path and also to the relay hostname (in order to prevent these events from being sent to other relays and groups out of context and cause confusion).

e and p tags can also be used to signal an immediate reply to another message on the group or to call for the attention of some other group user.

When inserting references -- in the body of the text -- to users, other messages (quotes) and to other Nostr events that outside of the group must be made following the NIP-27 pattern (nostr:nevent1...).

  "kind": 9,
  "content": "hello my friends lovers of pizza",
  "tags": [
    ["g", "/flavors", "pizza.com"]
  ]
  ...
  • group metadata (kind:39000) (mandatory)

f this event does not exist, the group should be identified in the client UI by its identifier (i.e. "/flavors" or "pizza.com/flavors"). All tags are optional. Having the "private" tag means the group cannot be read and relays will use NIP-42 AUTH messages to control who can read from it. The "closed" tag means the group can be read by anyone but only explicitly whitelisted pubkeys are allowed to post, again these enforcements happen at the relay level.

This event will follow NIP-33 (Parameterized Replaceable Events) to be replaced by a new event whenever there is a change to metadata such as add user, remove user or change user permissions. This event is valid only when it is signed by the relay. Relay may enforce other conditions such as unique group name, number of users per group and group type.

Group Tag cannot be changed after creation.

Subgroups like /flavors/pepperoni will have its own 39000 event but will not have users or roles. They will inherit them from /flavors. They are mainly used as filters within the group. subgroups can only be created by admins of top level group.

  {
    "kind": 39000,
    "content": "a nip-29 chat group for debating pizza flavors and other topics",
    "tags": [
      ["d", "/flavors"],
      ["name", "Pizza Lovers"],
      ["picture", "https://pizza.com/pizza.png"],
      ["read", "public" | "private"],  //default public
      ["write", "closed" | "open"],  //default closed

    ]
    ...
  }
  • group admins (kind:39001) (mandatory)

This event will hold all the user pubkeys that are part of this group with roles.

[ "p", "<pubkey1-as-hex>", "role1", "role2"...],

"pubkey1-as-hex" and "role 1" are mandatory role2 and above are optional.

Role 1 should have a minimum of two types such as "admin" and "user" where admin can modify metadata and users cannot. Fine grained controls can be added after role 1 to further define the user fine grained controls.

e.g. ["<pubkey1-as-hex>", "admin", "add-user", "edit-metadata", "delete-message", "ban-user"],
{
  "kind": 39001,
  "content": "",
  "tags": [
    ["d", "/flavors"],
    ["p", "<pubkey1-as-hex>", "role1", "role2"...],
    ["p", "<pubkey2-as-hex>", "role1", "role2"...]
  ]
  ...
}

Group names will follow the nostr:naddr scheme to point to the group directly. client will match the relay pubkey to NIP-11 relay document to confirm it is valid.

  
  naddr {
  identifier: '/flavors',
  pubkey: <relay pubkey>,
  kind: 39000,
  relays: [ 'wss://pizza.com' ]
}
  • Group action event (kind:9000) (mandatory)

An event sent from a client to the relay in order to accomplish a change to group metadata. The relay should read this event and act on it if the user sending the event has the required permissions and the date is close to the current date. If the group does not exist, then relay will create kind-39000 event and make this event pubkey as "admin". The relay may discard the event after taking action or keep it as a way to expose a group action log. This is similar to the kind:9 event in its structure.

{
  "kind": 9000,
  "content": "action description and/or reason",
  "tags": [
    ["g", "/flavors", "pizza.com"],
    ["action", "add", "<pubkey-to-add>", "user"],
    ["action", "remove", "<pubkey-to-remove>"],
    ["action", "change", "<pubkey-to-remove>", "admin"],  //change user role
    ["action", "change", "name", "Iceream lovers"],  //if name need to change
    ["action", "change", "picture", "https://pizza.com/pizza2.png"],  
,
  ]
}

Admin/group creation flow:

  • Goto relay webpage.
  • register/pay to get access
  • Click add to create a group
  • Fill in metadata info, add initial users
  • create/sign event 9000 and submit it to relay.
  • Relay takes info and signs it with its key and creates event 39000 and provides a nostr:naddrxx that can be shared with other users.

User flow

  • Click on nostr:addrxx link and it will open the relay registration page if it is first time. If the user pubkey is already registered then it can NIP-42 Auth and go inside the group.
  • If not, user can register/pay for the relay to get NIP42-Authed.
  • Relay will then provide a list of all 39000 events in that relay
  • In the list of groups, click any group and subscribe.
  • See list of events inside that group and also post new messages in the group.