Manage membership in Seige
Check seige.capabilities() before offering family controls. Handle errors separately from a null familySharing capability. From a user action, call seige.households.manage(). The Seige window can create a household, invite a recipient username, accept an invitation and approve member keys. Select the households whose names and scoped membership IDs this app may see, then approve.
The SDK receives no invitation credential or global account directory. The owner must approve a new member's keys. If necessary, the owner can use Update shared keys in Seige to deliver existing workspace keys to an approved member.
manageButton.onclick = async () => {
const managed = await seige.households.manage();
if (managed.error) return showError(managed.error);
const result = await seige.households.list();
if (result.error) return showError(result.error);
renderHouseholdChoices(result.data);
};
Approve a workspace for each installation
The household owner calls shared.create({householdId,name}) from a separate button. Creation opens a Seige approval window. Members discover this app's resources with shared.list({householdId}), then call shared.requestAccess({resourceId,access:["read","write"]}) from a user action. A read-only installation requests ["read"]. Each browser approves separately. Membership does not grant app access, and personal folders remain separate.
const opened = await seige.shared.open({ resourceId });
if (opened.error) return showError(opened.error);
const workspace = opened.data;
const snapshot = await workspace.read();
if (snapshot.error) return showError(snapshot.error);
renderRecords(snapshot.data.records);
Record payloads are Uint8Array values. The SDK verifies the writer signature, server receipt and encrypted batch before returning them. record.memberId is the verified publisher's household-scoped identity. Editable labels inside a payload do not prove who originally wrote or requested an item.
Publish with revisions and stable mutation IDs
const result = await workspace.mutate({
mutationId: crypto.randomUUID(),
expectedRevision: snapshot.data.revision,
schemaVersion: 1,
records: [{ objectId, payload: new TextEncoder().encode(JSON.stringify(edit)) }]
});
if (result.error) return showError(result.error);
showPublication(result.data);
Only published confirms server acceptance. The SDK saves one encrypted exact signed packet per workspace before sending it. Use the same mutation ID for a retry of the same contents. pending needs reconnection; conflict needs a new read and deliberate application-level merge. The SDK does not merge records or SQL. Keep a draft until the result is resolved. Mutations support at most 100 records and 256 KiB plaintext. Set deleted:true for a verified tombstone.
workspace.pending() returns decrypted queued records for review or export. workspace.retry() replays the exact packet. After reviewing a conflict, pass replacePending with its known mutation ID to explicitly replace it with a merged mutation. Never automatically discard a conflicting edit.
Read after invalidation
shared.subscribe({resourceId,cursor,signal}) returns a Result containing an AsyncIterable. Iterate inside a try/catch, reread authoritative records after hints, and reconnect using the last loaded revision. Hints contain no content. Defer applying new data while the person is editing. Snapshot pagination can reject a concurrent revision change; retry the full read. Close handles and clear displayed records when accounts or access change.
Recover after removal
Removal immediately blocks the member's access and queued publication, and freezes new workspace writes. The owner calls shared.rotate({resourceId}) from a user action to distribute a fresh key to remaining members. Every browser then approves access again. Old copied content and old keys cannot be recalled.
Retain queued changes until the person makes an explicit recovery choice. shared.pending({resourceId}) returns local queue metadata even after removal; shared.discardPending({resourceId,mutationId}) explicitly discards it. Decrypting or exporting queued records requires approved keys. Keep personal mode available through an explicit choice rather than silently switching a failed shared view.
Related guides
This guide is also available as Markdown for coding agents.