SqlDelightClientStorage

Persistent ClientStorage on SQLite through SQLDelight, with record-level encryption of the sensitive records (docs/storage-encryption.md).

Open it with open. The application creates the SqlDriver for its platform with Schema (for example JdbcSqliteDriver, AndroidSqliteDriver, NativeSqliteDriver), and closes it. Every transaction is a real SQLite transaction: if the block throws, SQLite rolls back all of its writes. A Mutex serializes transactions of this instance; use one instance per database.

The JVM and native drivers bind a transaction to the thread that started it. Transaction blocks must not move to another thread, so they must not suspend on I/O or switch dispatchers. SecureMessageClient follows this. Sealing and opening records is CPU work inside the transaction.

The local identity, the device authentication key, signed and one-time prekeys (whole key pairs), session state, pending message frames (sent and received) and the content digests of finalized (committed or discarded) received messages are stored as AES-256-GCM records bound to their record type and row key. IDs, addresses, timestamps, sequence numbers, high-water marks, remote identity pins, retired initiations, processed message IDs, their finalization and discard reason stay plaintext metadata. There is no unencrypted mode. A record that does not authenticate throws StorageEncryptionException; it is never treated as missing.

Schema version 2 added the remote_identity table (milestone 5), version 3 the retired_session_initiation table (milestone 6), version 4 nullable signed prekey lifecycle columns (milestone 7), version 5 the pending_outbound_message and processed_inbound_message tables (milestone 8), version 6 the storage_encryption marker (milestone 9), version 7 the storage key rotation state (milestone 11), version 8 the device_authentication_key and device_authentication_state tables (milestone 12, docs/server-authentication.md), version 9 the device_authentication_recovery_key table (milestone 14, docs/device-recovery.md), version 10 the remote_identity.verification column (milestone 15, docs/identity-verification.md), version 11 the device_authentication_rotation_key table (milestone 16, docs/device-authentication-rotation.md), version 12 the device_authentication_last_device_recovery_key table (milestone 18, docs/last-device-recovery.md), version 13 the pending_inbound_message table and the processed_inbound_message commit time and digest (milestone 20, docs/application-delivery.md), version 14 the processed_inbound_message finalization and discard reason and the sender pagination index (milestone 21, docs/message-discard.md), version 15 the pending_outbound_message recipient pagination index (milestone 22, docs/outbound-message-lifecycle.md), version 16 the storage_encryption.migration_intent column (S1, finding F7, docs/storage-encryption.md). A driver created with Schema upgrades an older database on open; an application that manages versions itself calls Schema.migrate(driver, oldVersion, Schema.version). An upgraded database still holds its milestone 8 plaintext until open encrypts it. Session state written before milestone 6 stays readable; its format is versioned inside the record. Timestamps are stored as epoch milliseconds.

Types

Link copied to clipboard
object Companion

Properties

Link copied to clipboard
Link copied to clipboard
open override val identity: IdentityStore
Link copied to clipboard
Link copied to clipboard
Link copied to clipboard
open override val preKeys: PreKeyStore
Link copied to clipboard
Link copied to clipboard
Link copied to clipboard
Link copied to clipboard
open override val sessions: SessionStore

Functions

Link copied to clipboard
suspend fun resumeStorageKeyRotation(maxRecords: Int = DEFAULT_ROTATION_BATCH): StorageKeyRotationStatus

Advances a storage key rotation by one step and returns the new status:

Link copied to clipboard

Starts a storage key rotation and returns the new current key ID.

Link copied to clipboard

The storage key rotation state (docs/storage-key-rotation.md). Key IDs only.

Link copied to clipboard
open suspend override fun <T> transaction(block: suspend ClientStorage.() -> T): T