The type of the history store to use for the group, must implement the BaseGroupHistory interface. (Default is no history store)
The type of the history store to use for the group, must implement the BaseGroupHistory interface. (Default is no history store)
ReadonlyciphersuiteThe ciphersuite implementation to use for the group
ReadonlyhistoryThe storage interface for the groups application message history
The group id as a hex string
ReadonlymediaThe storage interface for the groups media
ReadonlymediaOptional media helper for group encrypted attachments.
ReadonlynetworkThe nostr relay pool to use for the group
ReadonlyruntimeRuntime publisher for driving session effects through transport.
ReadonlysessionProtocol state owner for this group. Prefer this over convenience methods.
ReadonlysignerThe signer used for the clients identity
ReadonlystoreThe key-value backend where serialized group state bytes are persisted
The group's derived convergence status (group-state.md §Convergence
status, B5): Syncing / Resolving / Settled / Blocked. Recomputed on
read against the clock, so it advances to Settled once the quiescence
window elapses with no further convergence-relevant input.
The live full-fork history tree: every group state observed (the canonical
branch and every fork), keyed by MLS confirmation tag. Exposes synchronous
structural queries (node, childrenOf, tips, path, ancestors,
lowestCommonAncestor) and async snapshot access (stateAt,
commitMessageOf). For a serializable rendering snapshot use
forkTreeView.
Complete group info/debug model for chat panels and diagnostics.
The group's lifecycle state (group-state.md). A new local commit may only
be prepared while Stable; the commit flow moves through PendingPublish
(commit prepared, publish unconfirmed) and Merging (publish acked, staged
commit applying) and back to Stable.
The failed subset of welcomeDeliveries — the invitees a founding create has not yet reached. Retry with retryWelcome.
Carries the same R-04 warning as welcomeDeliveries: this is in-memory only, lost on restart, and ignorable by a caller that never reads it. The only recovery beyond retryWelcome is the spec's re-invite-with-a-fresh-KeyPackage path (refs/marmot/protocol-core/publish-lifecycle.md lines 66-78).
Account-identity-proof profile support is orthogonal to membership
status (D-11): a stored group whose GroupContext does not classify as
the current profile (legacy, mixed, or missing the 0x8009 requirement)
stays listable and destroy()-able, but every outbound send and every
inbound event is refused. Delegates to session.profileSupport, which
recomputes from the engine on every access.
Read the current group state
Public absorbing status; Unrecoverable deliberately remains active/repairable.
The FOUND-04 per-invitee Welcome delivery report: one entry per recipient a founding create attempted to deliver to, in delivery order.
This is in-memory only and is lost on restart or crash (D-04). It is discoverable state, not a returned value or a thrown error — a caller that never reads it silently loses an invitee who is already a member at epoch 1. The only recovery is the spec's re-invite path: the founding creator MAY re-invite the unreachable member with a fresh KeyPackage against the now-canonical group (refs/marmot/protocol-core/publish-lifecycle.md lines 66-78). This is an accepted consequence of D-04 + D-10 + D-12, not an oversight (R-04).
Decrypts an encrypted-media-v1 attachment downloaded from a blob store.
On the first call for a given file the plaintext bytes are derived via
key-derivation + ChaCha20-Poly1305 decryption (after verifying the
ciphertext and plaintext hashes) and stored in {@link media}. Subsequent
calls for the same attachment.ciphertextSha256 are served directly from
the cache, skipping key-derivation entirely.
Fans out a founding Welcome to every invitee, one NostrWelcomeDelivery.deliverMany call reached directly through
runtime.welcomeDelivery (D-05/D-07) — this bypasses GroupRuntime's
publish path entirely, since a founding Add has no GroupPublishWork to
drive. Retains the Welcome and author so a failed recipient can be
retried later via retryWelcome.
Never throws and never saves: partial or total Welcome failure is a
normal outcome (D-12), reported through pendingWelcomes rather
than raised. GroupFactory.create refuses a founding create without
valid group relays (CR-01), so on the factory path this group always
carries relays; the group-relay list is forwarded both as each Welcome
rumor's required relays tag and as deliver's inbox-lookup fallback, and
a recipient whose own inbox lookup resolves empty still fails
independently of the others.
Destroys the group and purges the group history
Persists irreversible intent, publishes one candidate, and retains it until selection.
Releases in-memory resources without touching persisted state (B5): cancels the settle-check timer and fails any queued outbound. Call on unload so a timer/promise does not outlive the cached instance.
Atomically enables lifecycle-v1 for a legacy group and publishes it once.
Encrypts a media file for sharing in a group message (encrypted-media-v1).
Derives the per-file key from the current MLS epoch, encrypts with ChaCha20-Poly1305, and returns the ciphertext alongside a populated MediaAttachment (hashes, nonce, media type, filename) with no locators yet.
Caller responsibilities:
encrypted to a blob store (ciphertextSha256 is the content id).{ kind, value }) onto attachment.locators.encodeMediaImetaTag and include the tag on the rumor.Evaluates whether a candidate's KeyPackage event (kind 30443) can be added
to this group — cipher-suite match, required_capabilities,
agent-text-stream-QUIC required_member_roles, and already-a-member. Use
this before GroupsManager.invite to surface why a KeyPackage can't be
added; an eligible: true result is safe to invite. Never throws.
A plain, serializable snapshot of the fork-history tree for debugging UIs — every node with its epoch, parent/children, tip flag, and whether it lies on the canonical path to the live tip (the branch convergence settled on, i.e. the node matching state). Computed on demand.
ingests an array of group messages and applies commits to the group state.
Processing happens in two stages:
refs/marmot/protocol-core/group-messaging.md
(sorted by epoch, timestamp, event id)
After both stages, recursively retry unreadable messages until no more can be read. Events that can never be processed are yielded as UnreadableIngestResult.
Array of Nostr events containing encrypted MLS messages
Optionaloptions: { maxRetries?: number }DispositionedIngestResult - The processing result plus its inbound-processing Disposition.
Optionalfn: (Optionalcontext: unknownOptionalonce: booleanAdd a listener for a given event.
Optionalcontext: unknownAdd a one-time listener for a given event.
Optionalcontext: unknownGroup transport events received but not yet decrypted/processed into the fork-history tree — the engine's ingestion pool (oldest-first). Normally transient (a message awaiting its commit, a fork message awaiting its branch); they are retried as the tree grows. An entry that lingers is a received event the client could never read — a gap a full-history debugger surfaces, since the unlocking state never arrived.
Creates and publishes a proposal as a private MLS message.
Promise resolving to the publish response from the relays
Creates and publishes a proposal as a private MLS message.
Promise resolving to the publish response from the relays
Realizes durable terminal notification exactly once across restarts.
Realizes a persisted removal after the owning registry has attached its forwarding listeners. This is idempotent across concurrent loads and process restarts when a removal marker store is configured.
Re-scores the persisted fork history against the current tip and switches to
the canonical branch if a competing fork now wins (convergence.md),
persisting a resulting switch. Candidates come from the forkTree, so a
client that diverged onto a losing fork converges from disk without waiting
for the network to re-deliver the winning branch. Called automatically on
load; safe to call explicitly to force a re-evaluation.
CR-06: the pass's results are routed through the SAME marker-clearing branch ingest uses, so a load-time rewind that supersedes the commit which removed us clears the persisted removed-inactive marker. Previously every result here was discarded, so the documented "called automatically on load" path could never clear it and a client restored to membership kept a stale marker that silently suppressed its next genuine removal.
Remove all listeners, or those of the specified event.
Optionalevent: keyof MarmotGroupEvents<THistory, TMedia>Remove the listeners of a given event.
Optionalfn: (Optionalcontext: unknownOptionalonce: booleanResumes a durable terminal intent after hydration when preparation is
eligible. Also the single seam #settleAndDrive uses to resume a pending
request mid-session, so both resume paths share one predicate.
Re-delivers one invitee's founding Welcome. Throws naming pubkey when
there is no matching delivery outcome, or when no founding Welcome is
retained (for instance after a restart) — this fails loudly rather than
silently no-opping, since a silent no-op is exactly R-04's failure mode.
When the matching entry already succeeded, returns it unchanged without
performing another delivery.
Deliberately has no epoch guard: RESEARCH Priority Finding #1
establishes that a late epoch-1 Welcome is safe because the joiner's
backfill (GroupsManager#connectGroup) has no since bound, provided
the group has relays. GroupFactory.create no longer produces
relay-less founding groups (CR-01), so on the factory path the relays
precondition always holds.
Persists any pending changes to the group state in the store.
When true, writes the current state even if dirty is
false. Useful for persisting the initial state of a freshly constructed
group (e.g. after createGroup / joinGroupFromWelcome / import) without
having to mutate dirty externally.
Performs a self-update commit (no proposals) to rotate this member's leaf key material.
This is required by refs/marmot/protocol-core/joining.md for forward
secrecy after joining from a Welcome.
Unlike admin commits (see GroupsManager.commit), this operation is allowed for non-admin members.
Sends a proposal to the group relays
Convergence-gated outbound entry point (B5). While convergence is Settled
and the lifecycle allows outbound, the intent is built, encrypted, and
published immediately. Otherwise it is queued and the returned promise stays
pending until the quiescence window settles and the queue drains — so app
payloads are held, and group-state commits are (re)generated only against the
canonical post-settle state. leave() and the self_remove auto-committer
bypass this gate by design (departures and convergence progress, not fresh
local intents).
StaticfromCreates a new MarmotGroup instance from a ClientState object
StaticprefixedOptionalcontext: anyCalls each of the listeners registered for a given event.
Return an array listing the events for which the emitter has registered listeners.
Return the number of listeners listening to a given event.
Return the listeners registered for a given event.
The main class for interacting with a MLS group