5c40e27fde
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.
3.1 KiB
3.1 KiB
EGG-08: Scheduling
status: draft
requires: EGG-01
category: optional
Summary
A host can announce a room before it opens by publishing a kind:30312
with status="planned" and a ["starts", <unix-seconds>] tag. Listing
clients render these as upcoming-room cards; the audio plane stays cold
until the host transitions the room to open.
Wire format
{
"kind": 30312,
"pubkey": "<host pubkey hex>",
"tags": [
["d", "<room d>"],
["room", "<room name>"],
["status", "planned"],
["starts", "<unix seconds>"],
["service", "<...>"],
["endpoint","<...>"],
["p", "<host pubkey>", "<relay hint>", "host"]
// ...other EGG-01 tags
],
"content": "",
...
}
The starts value is a base-10 ASCII unix timestamp in seconds. Clients
that need finer-than-second precision are out of scope; round to the
nearest second.
Behavior
- A planned room MUST carry
status="planned"AND astartstag with a non-empty numeric value. A planned room without astartsvalue MUST be treated as un-renderable (rooms with unknown start times pollute the listing UI). - The
startsvalue SHOULD be in the future at the time the event is published. Receivers MUST tolerate past values: a planned room whosestartsis in the past renders as "starts soon" rather than surfacing the past time. - To start a planned room, the host MUST re-publish the same
(kind, d)withstatus="open"and a highercreated_at. The host MAY drop thestartstag at this point (no longer informative). - To cancel a planned room, the host MUST re-publish the same
(kind, d)withstatus="closed". Thestartstag SHOULD be preserved so receivers can label the cancellation ("Cancelled — was scheduled for ..."). - Planned rooms MUST NOT mint moq-auth tokens (EGG-02). The auth sidecar
SHOULD reject
POST /authrequests targeting a(host, room d)whose most-recentkind:30312isstatus="planned". - Listing UIs SHOULD sort planned rooms ahead of live ones until 5
minutes before
starts, then promote the room to the same surface as live rooms (the host is unlikely to be more than 5 minutes late). - A peer MUST NOT use
["expiration", <ts>](NIP-40) on a plannedkind:30312. The implicit 8-hour staleness window from EGG-01 is the only auto-close mechanism.
Example
{
"kind": 30312,
"pubkey": "abc...host",
"created_at": 1714000000,
"tags": [
["d", "monthly-q-and-a"],
["room", "Monthly Q&A"],
["summary", "Bring your questions"],
["status", "planned"],
["starts", "1714172400"],
["service", "https://moq.nostrnests.com"],
["endpoint", "https://moq.nostrnests.com"],
["p", "abc...host", "wss://relay.example", "host"]
],
"content": "",
"id": "...",
"sig": "..."
}
Compatibility
Receivers without EGG-08 see a planned room as status="planned" and
SHOULD treat it as un-joinable per EGG-01 rule 6 (status-not-open
means non-renderable for live UIs). The room becomes joinable as soon
as the host re-publishes with status="open".