# Private groups

Marmot membership, collections, and device lifecycle.

[Read the shared private collections guide](/docs/groups/). Signatures below come from the published SDK declarations. Access SDK services through `db`; use their constructors only when integrating at a lower level.

## GroupsOptions


```ts
/** Encrypted device-local storage. Reuse the device id and adapter across restarts. */
interface GroupsOptions {
  deviceId?: string;
  adapter?: GroupStateAdapter;
}
```

## CreatePrivateGroupOptions


```ts
interface CreatePrivateGroupOptions {
  name: string;
  description?: string;
}
```

## PrivateGroupInfo


```ts
interface PrivateGroupInfo {
  id: string;
  name: string;
  description: string;
  members: string[];
  admins: string[];
  status: "active" | "removed" | "disbanded";
  epoch: bigint;
}
```

## PrivateGroupInvite


```ts
interface PrivateGroupInvite {
  id: string;
  author: string;
  name: string | null;
  description: string | null;
  joinable: boolean;
}
```

## GroupChangePayload


```ts
type GroupChangePayload<T extends object> = ChangePayload<T> & {
  groupId: string;
};
```

## NostrbaseGroups


```ts
/** Shared private collections using the pinned Marmot engine. */
declare class NostrbaseGroups<DB extends SchemaShape<DB> = DefaultSchema> {}
```

### Properties


```ts
readonly host: NostrbaseClient<DB>;
readonly deviceId: string;
```

### constructor


```ts
constructor(host: NostrbaseClient<DB>, options?: GroupsOptions);
```

### create


```ts
create(options: CreatePrivateGroupOptions): Promise<Result<NostrbaseGroup<DB>>>;
```

### get


```ts
get(id: string): Promise<Result<NostrbaseGroup<DB>>>;
```

### list


```ts
list(): Promise<Result<PrivateGroupInfo[]>>;
```

### exportStateBackup


```ts
/** Export encrypted MLS/device state for this account and stable device ID. */
exportStateBackup(): Promise<Result<GroupStateBackup>>;
```

### importStateBackup


```ts
/** Import encrypted MLS/device state. Use the same account and stable device ID. */
importStateBackup(
  archive: GroupStateBackup | string,
): Promise<Result<GroupStateBackupImport>>;
```

### publishKeyPackage


```ts
/** Publish the public device KeyPackage and discovery lists on configured relays. */
publishKeyPackage(): Promise<Result<WriteReceipt[]>>;
```

### invites


```ts
invites(): Promise<Result<PrivateGroupInvite[]>>;
```

### join


```ts
join(inviteId: string): Promise<Result<NostrbaseGroup<DB>>>;
```

### flush


```ts
/** Retry exact envelopes and outstanding Welcomes; no new ciphertext is made. */
flush(options?: { signal?: AbortSignal }): Promise<Result<WriteReceipt[]>>;
```

### runExclusive


```ts
/** @internal Serialize SDK mutations with device recovery. */
runExclusive<T>(callback: () => Promise<T>): Promise<T>;
```

### hasReplayPending


```ts
/** Inspect only this account/device's durable obligations before loading Marmot. */
hasReplayPending(): Promise<boolean>;
```

### replayQueued


```ts
/** Automatic replay reloads handles after recovering exact publication obligations. */
replayQueued(options?: { signal?: AbortSignal }): Promise<Result<WriteReceipt[]>>;
```

### close


```ts
close(): void;
```

### closeAsync


```ts
closeAsync(): Promise<void>;
```

## NostrbaseGroup


```ts
/** A private Marmot scope with the same awaitable query builder as public tables. */
declare class NostrbaseGroup<
  DB extends SchemaShape<DB> = DefaultSchema,
> implements QueryHost {}
```

### Properties


```ts
readonly id: string;
get info(): PrivateGroupInfo;
```

### constructor


```ts
constructor(
  host: NostrbaseClient<DB>,
  context: GroupContext<DB>,
  group: MarmotGroup,
  journal: GroupRecordJournal,
);
```

### ready


```ts
/** Complete any encrypted receive journal left by an interrupted ingress. */
ready(): Promise<void>;
```

### from


```ts
from<K extends keyof DB & string>(table: K): QueryBuilder<DB[K]>;
```

### sync


```ts
sync(): Promise<Result<PrivateGroupInfo>>;
```

### invite


```ts
invite(pubkey: string): Promise<Result<WriteReceipt[]>>;
```

### remove


```ts
remove(pubkey: string): Promise<Result<WriteReceipt[]>>;
```

### rotate


```ts
rotate(): Promise<Result<WriteReceipt[]>>;
```

### leave


```ts
leave(): Promise<Result<WriteReceipt[]>>;
```

### subscribe


```ts
subscribe<K extends keyof DB & string>(
  table: K,
  callback: (change: GroupChangePayload<DB[K]>) => void,
  onError?: (error: NostrbaseError) => void,
): {
  unsubscribe(): void;
};
```

### executeInGroup


```ts
/** A group handle can only select its own encrypted scope. */
executeInGroup<T extends object>(
  groupId: string,
  table: string,
  state: QueryState,
): Promise<Result<Row<T>[]>>;
```

### execute


```ts
execute<T extends object>(
  table: string,
  state: QueryState,
): Promise<Result<Row<T>[]>>;
```

### flush


```ts
/** Catch up membership, then encrypt queued signed record intents for the current epoch. */
flush(options?: { signal?: AbortSignal }): Promise<Result<WriteReceipt[]>>;
```

### dispose


```ts
dispose(): void;
```


## Supporting declarations

These types appear in public signatures but are not package exports.

### SignedGroupIntent


```ts
interface SignedGroupIntent {
  groupId: string;
  table: string;
  recordId: string;
  rumor: GroupRecordRumor;
  proof: NostrEvent;
  createdAt: number;
  envelopeId?: string;
}
```

### GroupContext


```ts
interface GroupContext<DB extends SchemaShape<DB>> {
  account: string;
  revision: number;
  engine: MarmotClient<undefined, undefined>;
  network: GroupNetwork;
  durability: GroupDurability;
  intents: EncryptedGroupStore<SignedGroupIntent>;
  ingress: EncryptedGroupStore<GroupRecordEntry>;
  welcomes: EncryptedGroupStore<NostrEvent>;
  projections: Map<string, GroupRecordJournal>;
  handles: Map<string, NostrbaseGroup<DB>>;
  pendingApplication: Map<string, GroupRecordRumor>;
  pendingSignals: Map<string, AbortSignal>;
  publicationSignals: Map<string, AbortSignal>;
  envelopes: Map<string, string>;
  receipts: Map<string, WriteReceipt>;
  welcomeAttempts: {
    groupId: string;
    eventId: string;
  }[];
  guard(): Promise<void>;
  projection(groupId: string): Promise<GroupRecordJournal>;
  closed: boolean;
}
```
