Keychain
Defined in: packages/core/src/keychain.ts:104
A keychain contains a PeerborneDocument’s encryption keys.
Keys are identified by a fixed-width binary key ID. Both
provisioning paths (add(), which generates random per-key
identifiers, and addEpochKey(), which installs BeeKEM-derived
epoch IDs from deriveEpochIdFromRootSecret) use the SAME byte
width — 32 bytes in the shipped Yjs / Automerge providers, surfaced
via KeychainProvider.keyIDLength. The matching width means the
wire-format encrypted-block key-ID prefix is a single fixed size for
any key the keychain has installed, regardless of how it was
provisioned: there is no truncation step, and getKey() never has to
disambiguate between key-ID encodings.
Type Parameters
Section titled “Type Parameters”KeychainChange
Section titled “KeychainChange”KeychainChange
Type of a block of change(s) describing edits made to the document keychain.
DocumentKey
Section titled “DocumentKey”DocumentKey
Type of a document encryption key.
Methods
Section titled “Methods”add():
Promise<[Uint8Array<ArrayBufferLike>,DocumentKey,KeychainChange]>
Defined in: packages/core/src/keychain.ts:110
Generates and adds a new document encryption key to the keychain.
Returns
Section titled “Returns”Promise<[Uint8Array<ArrayBufferLike>, DocumentKey, KeychainChange]>
The new document key ID, key, and a block of change(s) describing the keychain addition.
addEpochKey()
Section titled “addEpochKey()”addEpochKey(
epochId,key):Promise<KeychainChange>
Defined in: packages/core/src/keychain.ts:200
Add an encryption key for a specific epoch. The epoch ID is the
full HKDF output from deriveEpochIdFromRootSecret — the
KeychainProvider.keyIDLength-wide identifier (32 bytes in the
shipped providers) that also becomes the wire-format key-ID
prefix on subsequent encrypted blocks. No truncation: the byte
width is uniform across provisioning, storage, and the wire.
Parameters
Section titled “Parameters”epochId
Section titled “epochId”Uint8Array
The epoch ID, exactly KeychainProvider.keyIDLength
bytes wide. Implementations MUST reject a mismatched width instead of
truncating or padding it. The shipped providers require exactly 32 bytes
and store those validated bytes verbatim.
DocumentKey
The encryption key for this epoch.
Returns
Section titled “Returns”Promise<KeychainChange>
A block of change(s) describing the keychain addition.
current()
Section titled “current()”current():
Promise<[Uint8Array<ArrayBufferLike>,DocumentKey]>
Defined in: packages/core/src/keychain.ts:152
Gets the current encryption key that should be used to encrypt new changes.
Returns
Section titled “Returns”Promise<[Uint8Array<ArrayBufferLike>, DocumentKey]>
currentKeyChange()
Section titled “currentKeyChange()”currentKeyChange():
Promise<KeychainChange>
Defined in: packages/core/src/keychain.ts:183
Gets a block of change(s) describing only the current (most recent) key.
Used for current_only key distribution where new members receive the
current encryption key, not the full key history. This does not itself
redact retained CRDT operations encrypted during that epoch.
The returned value MUST be safe to regenerate and replay without creating
a second logical keychain entry, and byte-stable for the same logical key
tuple across repeated calls, restored instances, and equivalent replicas.
Implementations may synthesize a standalone projection only with stable,
content-derived CRDT operation identity; otherwise they MUST reject.
A one-key keychain MUST export its live history so receivers share the
author’s lineage and can merge the author’s next add() delta. Receivers
of a projected later key hold an independent lineage and cannot merge
rotation deltas authored on the full history.
Returns
Section titled “Returns”Promise<KeychainChange>
A replay-safe block of change(s) containing only the current key.
getKey()
Section titled “getKey()”getKey(
keyID):DocumentKey|undefined
Defined in: packages/core/src/keychain.ts:163
Looks up a document key by its ID.
Parameters
Section titled “Parameters”Uint8Array
An identifier for a document key. Provider implementations
define the width via KeychainProvider.keyIDLength and both
provisioning paths (add() and addEpochKey()) emit IDs of that
exact width.
Returns
Section titled “Returns”DocumentKey | undefined
The requested document key.
history()
Section titled “history()”history():
KeychainChange
Defined in: packages/core/src/keychain.ts:126
Gets a block of change(s) describing the whole state of the keychain.
Returns
Section titled “Returns”KeychainChange
A block of change(s) describing the keychain.
historySince()
Section titled “historySince()”historySince(
keyID):Promise<KeychainChange>
Defined in: packages/core/src/keychain.ts:275
Gets a block of change(s) describing only the keys at or after the given
key ID. Used for the since_invited history visibility mode where a new
member receives every key from the moment they were invited onward, but
no earlier epoch keys. It does not itself redact retained CRDT operations.
The returned value MUST be safe to regenerate and replay: repeated calls
for the same boundary and keychain state must not create fresh CRDT
actor/client operations that duplicate keys or change the visible window.
Implementations MUST reject when their CRDT cannot project the requested
suffix from stable existing operation history without including keys before
the boundary. In particular, an unknown, stale, or attacker-controlled
keyID MUST reject unless the implementation can derive a replay-safe
current-key-only change from existing operation history. Returning full
history would disclose every pre-invitation epoch.
Parameters
Section titled “Parameters”Uint8Array
The key ID marking the start of the visible window.
Returns
Section titled “Returns”Promise<KeychainChange>
A block of change(s) containing only keys at or after keyID.
keys()
Section titled “keys()”keys():
Promise<[Uint8Array<ArrayBufferLike>,DocumentKey][]>
Defined in: packages/core/src/keychain.ts:147
Gets the all document encryption keys in the keychain.
Returns
Section titled “Returns”Promise<[Uint8Array<ArrayBufferLike>, DocumentKey][]>
all document encryption keys.
merge()
Section titled “merge()”merge(
change):void
Defined in: packages/core/src/keychain.ts:140
Merges in a block of change(s) to the keychain.
Parameters
Section titled “Parameters”change
Section titled “change”KeychainChange
A block of change(s) to apply.
Returns
Section titled “Returns”void
prepareAppend()
Section titled “prepareAppend()”prepareAppend(
change,intent):PreparedKeychainMerge<KeychainChange,DocumentKey>
Defined in: packages/core/src/keychain.ts:251
Stage an authenticated, predecessor-bound standalone key append. This is
distinct from prepareMerge() because append authority must be validated
explicitly.
Implementations MUST require a canonical one-key projection matching
expectedNewKeyId. They may append only when the live current key matches
expectedPreviousKeyId, or return an unchanged exact replay when the live
sequence already ends with the expected previous/new pair and material.
Parameters
Section titled “Parameters”change
Section titled “change”KeychainChange
intent
Section titled “intent”Returns
Section titled “Returns”PreparedKeychainMerge<KeychainChange, DocumentKey>
prepareEpochKey()
Section titled “prepareEpochKey()”prepareEpochKey(
epochId,key):Promise<PreparedKeychainEpoch<KeychainChange>>
Defined in: packages/core/src/keychain.ts:226
Stage an epoch-key insertion without mutating live keychain state. BeeKEM membership transitions finish all fallible signing, sealing, serialization, and block preparation before a synchronous keychain/tree commit.
commit() MUST either apply the staged state completely or throw before
mutation. It is called at most once, after every asynchronous preparation
step has succeeded.
Core transaction wrappers inspect both this capability and the returned
claimCommit capability without invoking accessors. Implement them as
ordinary prototype methods or own data-property functions.
The epochId width contract is identical to addEpochKey(): it must equal
KeychainProvider.keyIDLength, exactly 32 bytes in the shipped providers,
and a mismatch must be rejected before any state is staged or mutated.
The current BeeKEM wire protocols derive and authenticate fixed 32-byte
epoch IDs, so a custom provider with another key-ID width cannot implement
those transitions.
Parameters
Section titled “Parameters”epochId
Section titled “epochId”Uint8Array
The full-width epoch identifier.
DocumentKey
The encryption key for this epoch.
Returns
Section titled “Returns”Promise<PreparedKeychainEpoch<KeychainChange>>
prepareKey()
Section titled “prepareKey()”prepareKey():
Promise<PreparedKeychainAddition<KeychainChange,DocumentKey>>
Defined in: packages/core/src/keychain.ts:117
Stage generation and insertion of a random document key without mutating live state. Callers can finish fallible wire preparation before invoking the synchronous commit.
Returns
Section titled “Returns”Promise<PreparedKeychainAddition<KeychainChange, DocumentKey>>
prepareMerge()
Section titled “prepareMerge()”prepareMerge(
change):PreparedKeychainMerge<KeychainChange,DocumentKey>
Defined in: packages/core/src/keychain.ts:238
Stage a remote keychain merge for an atomic Welcome state commit. Core
transaction wrappers inspect this capability and the prepared
hydrateKeys, getKey, and claimCommit capabilities without invoking
accessors. Implement them as ordinary prototype methods or own
data-property functions.
Parameters
Section titled “Parameters”change
Section titled “change”KeychainChange
Returns
Section titled “Returns”PreparedKeychainMerge<KeychainChange, DocumentKey>
stateCommitment()
Section titled “stateCommitment()”stateCommitment():
Promise<Uint8Array<ArrayBufferLike>>
Defined in: packages/core/src/keychain.ts:133
Commit to the validated ordered logical key sequence independently of
provider-specific CRDT operation identities. Implementations MUST use
computeKeychainStateCommitment.
Returns
Section titled “Returns”Promise<Uint8Array<ArrayBufferLike>>