Files
amethyst/nestsClient/specs/EGG-04.md
T
Claude 5c40e27fde docs(nestsClient/specs): EGG-00..EGG-12 — Extensible Gossip Guidelines
Wire-protocol specs for nostrnests-style audio rooms, in the
style of Nostr NIPs and Blossom BUDs. Each spec documents one
self-contained capability that a client or relay can implement;
two compliant peers implementing the same set of EGGs round-trip
without further coordination.

Layout:

  README.md            cover, status table, conformance levels
  EGG-01.md  Room event (kind:30312)              required
  EGG-02.md  Auth + WebTransport handshake        required
  EGG-03.md  Audio plane (moq-lite)               required
  EGG-04.md  Presence (kind:10312)                required
  EGG-05.md  In-room chat (kind:1311)             optional
  EGG-06.md  Reactions (kind:7)                   optional
  EGG-07.md  Roles & moderation (kind:4312)       optional
  EGG-08.md  Scheduling (status=planned)          optional
  EGG-09.md  User server list (kind:10112)        optional
  EGG-10.md  Theming (c/f/bg tags)                decorative
  EGG-11.md  Recording                            decorative
  EGG-12.md  Catalog track (catalog.json)         optional

Conformance levels (Listener / Speaker / Host) defined in the
README so a deployment can declare "we implement EGG-01..EGG-04"
and other peers know exactly what to expect.

Each spec follows the same shape (Summary / Wire format /
Behavior numbered MUST/SHOULD/MAY rules / Example /
Compatibility) and fits on a single printed page. Wire formats
are documented exactly as nostrnests + amethyst implement them
on this branch — no hypothetical capabilities, no "future" tags
without an EGG number.
2026-04-27 03:54:45 +00:00

105 lines
3.6 KiB
Markdown

# EGG-04: Presence (`kind:10312`)
`status: draft`
`requires: EGG-01`
`category: required`
## Summary
Each participant in a room periodically broadcasts a `kind:10312` event
declaring their state: which room they are in, whether their hand is raised,
whether they are muted, whether they are actively pushing audio, and whether
they currently hold a stage seat.
Presence is the source of truth for the audience-side participant grid, the
hand-raise queue, the listener counter, and the home-screen "live" bubble.
## Wire format
`kind:10312` is a NIP-01 *replaceable* event with a fixed `d`-tag (one
presence-state per pubkey, regardless of how many rooms a user joins; see
"Behavior" below).
```json
{
"kind": 10312,
"pubkey": "<participant pubkey hex>",
"tags": [
["a", "30312:<host pubkey hex>:<room d>", "<relay hint>"],
["hand", "0" | "1"],
["muted", "0" | "1"],
["publishing", "0" | "1"],
["onstage", "0" | "1"],
["alt", "Room Presence tag"]
],
"content": "",
...
}
```
The `a` tag is REQUIRED and points at the room defined in EGG-01.
## Behavior
1. A participant MUST emit a `kind:10312` event:
- on entering the room,
- every 30 s while in the room,
- immediately when any flag (`hand`, `muted`, `publishing`, `onstage`)
changes,
- one final time on leaving, with `publishing="0"` and `onstage="0"`.
2. Receivers MUST treat a participant as departed if no presence has been
observed in `> 6 minutes`. (One missed heartbeat plus a 5 minute
tolerance window.)
3. The `hand` flag is the participant's request-to-speak. Hosts and admins
read it to populate a queue (EGG-07).
4. The `muted` flag is set ONLY by speakers who are also publishing. Pure
audience members SHOULD omit it.
5. The `publishing` flag means "I currently have an open `audio/data`
broadcast on the relay" (EGG-03). It MUST be `0` whenever the speaker
has stopped publishing, regardless of mute state.
6. The `onstage` flag means "I currently hold a speaker slot in the room's
`p`-tag list (EGG-01) AND I have not voluntarily stepped off". A
speaker who steps off the stage without losing the role tag MUST emit
`onstage="0"`.
7. The `d`-tag MUST be the FIXED string `nests-room-presence` (chosen so
that one presence event represents a participant's CURRENT room across
all clients). A participant MUST NOT be in two rooms simultaneously.
8. Every flag MUST be present in every emitted event. Receivers MAY assume
omitted flags default to `0`, but emitters that omit are non-conformant.
9. Hosts and clients displaying the participant grid MUST hide presences
from `kind:10312` events whose `created_at` is older than the staleness
window in rule (2).
## Example
```json
{
"kind": 10312,
"pubkey": "def...co",
"created_at": 1714003231,
"tags": [
["a", "30312:abchost:office-hours-2026-04", "wss://relay.example"],
["hand", "0"],
["muted", "0"],
["publishing", "1"],
["onstage", "1"],
["alt", "Room Presence tag"]
],
"content": "",
"id": "...",
"sig": "..."
}
```
## Compatibility
EGG-07 (moderation) reads `hand` to drive the host's promote queue.
EGG-03 (audio plane) is the source of truth for whether a speaker IS
broadcasting; presence's `publishing` flag is a Nostr-side reflection that
clients use as a hint when they cannot subscribe to the audio plane (e.g.
listeners on weak networks rendering the home bubble).
The `kind:10312` shape here intentionally mirrors `kind:10311` from
NIP-53 streaming so that a generic Nostr client can render audience
indicators for both protocols without code-paths.