Skip to main content

Module guestbook

Module guestbook 

Source
Expand description

CORD-02 §5 Guestbook Plane — membership motion, coalesced flat.

One Stream per Community (community_root-keyed, super::derive::guestbook_group_key), carrying ONLY membership motion: self-signed Joins/Leaves (3306), authorized Kicks (3309), and refounder-signed post-Refounding Snapshots (3312) — never messages, never authority (a Ban lives on the Control Plane). The plane is off-consensus: nothing in Control or Chat depends on it, so it loads last and can lag without harm.

Everything here is PURE — no DB, no network, no clock reads. The +1h forward-clock rule takes now_ms as a parameter, and the two authority questions arrive from the caller’s Control Plane fold: can_kick (the KICK bit + strict outrank) and snapshot_authority (the npub whose Refounding minted the epoch being folded).

Guestbook seals are ENCRYPTED (20013) by spec: a plaintext seal would make a member’s signed membership record liftable as a standalone public artifact, so parse_guestbook_event rejects the plaintext form outright.

Structs§

GuestbookEvent
One parsed guestbook event: the entry plus the identity the coalesce tie-break runs on — the INNER rumor id, never the wrap’s (a wrap id differs per re-wrap, and two clients holding different wraps of one rumor would fork on ties).
MemberState
One npub’s folded guestbook state — the winning entry, flat.

Enums§

GuestbookEntry
The typed guestbook entries (CORD-02 §5). Authors (member / actor / refounder) are the seal-verified real keys, proven by stream::open_wrap before parsing ever starts.
GuestbookError
Errors from the guestbook layer (envelope errors ride inside).
Source
Whether the winning entry was the member’s own word or a refounder’s secondhand snapshot seed.
Verdict
An npub’s final coalesced state.

Constants§

MAX_FUTURE_MS
Entries dated further than this ahead of the receiver’s clock are dropped outright (CORD-02 §5) — ample for deep clock skew, and the deterrent against squatting “latest” with a forged future date.
SNAPSHOT_CHUNK
Snapshot chunk size: 400 members per event (CORD-02 §5). 400 hex pubkeys of JSON is ~27 KB — comfortably inside the NIP-44 65,535-byte cap at every nesting layer, with headroom for the envelope.

Functions§

build_join_rumor
A self-signed Join, optionally echoing the invite attribution from the bundle that admitted the author (["invite", creator, label], CORD-05 §1).
build_kick_rumor
An admin-signed Kick naming its target and citing the Grant it acts under (the vac, CORD-04 §5) — absent when the owner acts (supreme, no grant to cite). Whether it’s honored is the reader’s call (coalesce’s can_kick), never the writer’s.
build_leave_rumor
A self-signed Leave.
build_snapshot_rumors
Refounder-signed snapshot rumors seeding a new epoch’s Guestbook: present members only, chunked at SNAPSHOT_CHUNK, every chunk carrying ["snap", <id>, <i>, <n>] (1-based) and ONE shared timestamp — the one-id-one-time invariant is what lets readers reject torn chunk sets. No survivors still yields one empty chunk, so the Refounding’s guestbook step is observable either way.
coalesce
Coalesce parsed guestbook events flat: one final MemberState per npub (CORD-02 §5), order-independent over events.
complete_memberlist
The Complete Memberlist: coalesced Joined members ∪ observed authors, minus the Banlist. observed maps author → the newest ms they were seen publishing anywhere in the Community (an author seen publishing is observably present, included even if their Join never arrived). Observation counts FORWARD only: it re-enters an author whose activity is strictly newer than their latest departure — a departed member’s old history can never resurrect them.
parse_guestbook_event
Parse a guestbook event from an ALREADY-VERIFIED OpenedStream (one produced by stream::open_wrap, which proved the seal signature, the author binding, the rumor id, and the strict ms). Strict on the seal form: guestbook rumors MUST ride encrypted seals (CORD-02 §5).
seal_guestbook_rumor
Seal a guestbook rumor (encrypted form) into a wrap at guestbook_pk. Local-keys convenience; bunker accounts use stream::seal_content + their remote signer + stream::wrap_seal for identical wire output.