| 1 | diff --git a/README.md b/README.md |
| 2 | index c226799..6bf3ebc 100644 |
| 3 | --- a/README.md |
| 4 | +++ b/README.md |
| 5 | @@ -50,6 +50,8 @@ See [Files and private repositories](docs/files-and-private-repositories.md) for |
| 6 | |
| 7 | See [Git collaboration](docs/git-collaboration.md) for issues, pull requests, conversation synchronization and participant outboxes. |
| 8 | |
| 9 | +See [Rooms](docs/rooms.md) for chat rooms inside a relay, open and members-only access, room administration, connecting Buzz-compatible clients and agents, and the live room stream. |
| 10 | + |
| 11 | See [Installed app](docs/app.md) for installing the relay as an app, sharing files to it, opening Nostr links and device notifications. |
| 12 | |
| 13 | See [Agent identities](docs/agents.md) for granting an assistant or bot its own scoped key, what the relay enforces and how to pause or revoke it. |
| 14 | diff --git a/docs/rooms.md b/docs/rooms.md |
| 15 | new file mode 100644 |
| 16 | index 0000000..decd1d2 |
| 17 | --- /dev/null |
| 18 | +++ b/docs/rooms.md |
| 19 | @@ -0,0 +1,66 @@ |
| 20 | +# Rooms |
| 21 | + |
| 22 | +A relay hosts chat rooms for its members. Each room is a [NIP-29](https://github.com/nostr-protocol/nips/blob/master/29.md) group with its own name, member list and admins, and any group chat client that speaks that dialect, including Buzz and agent gateways built on it, can take part. |
| 23 | + |
| 24 | +The relay's own group is the room whose id is the relay name. Its member list is the relay roster: the relay owner is the room owner and moderators are room admins. Its access follows the relay read rule, so a members-only relay has a members-only main room. The main room cannot be deleted. |
| 25 | + |
| 26 | +## Open and members-only rooms |
| 27 | + |
| 28 | +An open room accepts every member of the relay. A member joins by sending a join request or simply by posting; the first message adds them to the room. Anyone who can read the relay can read an open room. |
| 29 | + |
| 30 | +A members-only room is visible only to its members, the relay owner and moderators. Join requests are refused; a room admin adds people. Members of the relay who are not in the room see neither its messages nor its member list. |
| 31 | + |
| 32 | +People must be members of the relay before they can create, join or be added to a room. |
| 33 | + |
| 34 | +## Creating and administering rooms |
| 35 | + |
| 36 | +Any relay member can create a room. The room id is 1 to 64 characters of lowercase letters, digits, hyphen and underscore, and must be new. A room takes a name, an optional description and picture, and an access rule: open or members-only. The creator becomes the room owner. |
| 37 | + |
| 38 | +Each room has owners, admins and members. Owners and admins edit the room's name, description, picture and access rule, add members, set a member's role and remove members. Only an owner appoints another owner or removes one, and a room always keeps at least one owner: the last owner can neither leave nor be removed until another owner is appointed. Only an owner deletes a room, which removes its messages, member list and records. |
| 39 | + |
| 40 | +Members leave on their own. A member deletes their own messages; owners and admins delete anyone's messages in the room. |
| 41 | + |
| 42 | +The relay owner acts as an owner of every room and moderators act as admins of every room, so moderation covers rooms the moderators have not joined. Removing someone from the relay removes them from every room. |
| 43 | + |
| 44 | +The relay owner sets how many rooms may exist beside the main room with the `rooms` policy field. The default is 64. Set it to 0 to stop room creation; existing rooms keep working. |
| 45 | + |
| 46 | +## Connecting a client or agent |
| 47 | + |
| 48 | +Connect to the relay websocket and authenticate with [NIP-42](https://github.com/nostr-protocol/nips/blob/master/42.md). Every room event carries an `h` tag with the room id; an `h` tag that names no room is rejected. Subscribing with a `#h` filter returns the room's history and live messages. An unauthenticated subscription to a members-only room receives an authentication hint. |
| 49 | + |
| 50 | +The relay accepts these kinds inside a room: |
| 51 | + |
| 52 | +| Kind | Purpose | |
| 53 | +| --- | --- | |
| 54 | +| 9 | Chat message | |
| 55 | +| 11 | Thread | |
| 56 | +| 12 | Thread reply, with an `e` tag naming the thread | |
| 57 | +| 7 | Reaction | |
| 58 | +| 40002 | Rich content | |
| 59 | +| 40003 | Edit | |
| 60 | +| 20001 | Presence, delivered live and never stored | |
| 61 | +| 20002 | Typing, delivered live and never stored | |
| 62 | +| 9007 | Create room: `h` is the new id; `name`, `about`, `picture` and `visibility` (`open` or `members`) or `channel_type` describe it | |
| 63 | +| 9002 | Edit room: the same tags as 9007, or the bare `open`, `closed`, `public` and `private` markers | |
| 64 | +| 9000 | Add a member: a `p` tag with the pubkey and an optional role (`member`, `admin` or `owner`) in third position | |
| 65 | +| 9001 | Remove a member: a `p` tag | |
| 66 | +| 9021 | Join request, open rooms only | |
| 67 | +| 9022 | Leave | |
| 68 | +| 9005 | Delete messages: `e` tags naming messages in the room | |
| 69 | +| 9008 | Delete the room | |
| 70 | + |
| 71 | +Private messages between members travel as [NIP-17](https://github.com/nostr-protocol/nips/blob/master/17.md) gift wraps outside any room. |
| 72 | + |
| 73 | +The relay signs and publishes its own records for every room: 39000 with the room's name, description, picture, `closed` for a members-only room and `private` when the relay is members-only; 39001 listing owners and admins with their roles; and 39002 listing members. The relay also signs a 44100 notice when someone is added to a room and a 44101 notice when someone is removed, both tagged with the room's `h`. Clients cannot publish these kinds themselves. Records for a members-only room are served only to its members and the relay's moderators. |
| 74 | + |
| 75 | +Room events reach device notifications and relay push callbacks the same way as other events. A chat message, thread or reply that names a member in a `p` tag wakes their devices with the room name, as a reply when it answers their message and as a mention otherwise. |
| 76 | + |
| 77 | +## Browser tools |
| 78 | + |
| 79 | +The browser tools expose three read-only room queries to browser agents. `browserooms` lists the rooms the signed-in person can see with their member count and the time of the last message; it accepts `cursor` and `limit`. `browseroom` takes a room `id` and returns the room, its members with their roles and the newest messages, 100 at a time, with `next_cursor` for the next page. `browsethread` takes a room `id` and the thread's `event` id and returns the root with its replies, newest first, paged the same way. See [Browser tools](webmcp.md). |
| 80 | + |
| 81 | +## Live stream |
| 82 | + |
| 83 | +`GET /rooms/<id>/stream` delivers a room's new events as server-sent events. The request is authenticated by the browser session cookie or a [NIP-98](https://github.com/nostr-protocol/nips/blob/master/98.md) signature, and access follows the room's rule: anyone who can read the relay may follow an open room, and a members-only room answers with 401 without a session and 403 to non-members. |
| 84 | + |
| 85 | +Each event arrives as `event: message` with the JSON event as its data, in the order the relay accepts it, and only events the viewer may see are sent. A comment line keeps the connection alive every 25 seconds. The stream closes when the client disconnects, when the relay begins maintenance or when it shuts down; reconnect and fetch recent history with `browseroom` to fill any gap. |