Skip to main content

Crate coven_core

Crate coven_core 

Source
Expand description

coven — end-to-end encrypted, multi-writer, bring-your-own-storage SQLite sync, with an encrypted blob store and a cryptographic membership model.

The host app owns its SQLite schema and domain. coven owns the sync layer: changesets captured via the SQLite session extension, HLC-stamped and signed per author, encrypted and pushed/pulled through a pluggable CloudHome, conflict-resolved per row by _updated_at arbitration with a column-level premerge so concurrent edits to different columns of a row survive. An append-only Ed25519-signed membership chain wraps the per-store symmetric key to each member.

Integration contract for the host:

  • coven OWNS the SQLite connection. The host opens it once with [Coven::builder(config)], declares synced tables and its synced-schema Migration ladder, and calls open: coven installs or verifies its one current internal schema, then runs the host’s migration ladder over PRAGMA user_version for the app’s tables and seeds the register clock off the rows on disk. The host runs its SQL through [CovenHandle::sql] or [CovenHandle::write]; coven captures each write into the pending-changeset journal as it commits, inside its own journaled transaction.
  • Every synced table has an id text primary key at column 0 and an _updated_at TEXT NOT NULL column, and is declared as a SyncedTable in the builder’s synced_tables set with a required RowIdentity. (table, id) is one logical row across every device. Independently created rows use canonical UUIDv4 or UUIDv7 ids; shared-key tables intentionally merge equal application keys. A primary-key change removes the old identity and inserts the new validated identity. A plain sync::session::SyncedTable::new table syncs unconditionally; sync::session::SyncedTable::remote_root also syncs the whole table and makes blobs on the row or its FK-descendants always Remote; sync::session::SyncedTable::gated_by marks a gated root whose boolean gate column decides, per row, whether that row and its declared FK-descendants are shared. See [sync::gate] for the gating semantics.
  • _updated_at is coven’s last-writer-wins register, an opaque Hybrid Logical Clock stamp the host mints with [SqlContext::stamp] and binds into every synced-row write. The host must not parse or compare the stamp as a wall-clock time; coven advances the clock past pulled rows so a later local write always sorts causally after them, which a wall clock cannot guarantee under skew.
  • When a cloud provider is connected, the host calls [CovenHandle::connect_sync]. Which rows carry blobs is declared per table via sync::session::SyncedTable::carries_blob; the host also supplies an optional blob::BlobTransitionObserver to the builder. A local-only store that never connects a provider still reads and writes through the handle.

§Blob storage model

A blob is opaque bytes a synced row references — a photo, an audio file, a cover image. Each blob declares two orthogonal properties and has one runtime state. [blob] holds the full concept tree; the summary:

  • Provenance (blob::Provenance) — where the bytes live while the blob is Local. User-provided: the user’s own file at a path coven references (the Remote→Local restore writes back to a user path, so it needs one). Host-provided: data the host hands coven, which coven keeps in its own local store at storage/local/<namespace>/<id> (no path needed to restore).
  • Cache fill (blob::CacheFill) — how a device gets the bytes while the blob is Remote. CacheEager fetches into the cache on pull (cover art, so a grid renders from local bytes); CacheLazy fetches on first read (audio).
  • Locality — the state: Local (bytes on-device, in the user’s file or coven’s local store) or Remote (bytes in the cloud, each device’s copy a cache copy). make_remote uploads the bytes and flips a gated root’s gate on; make_local brings them back to a local file and flips it off (see [blob::transition]). A remote root starts Remote and rejects those transitions.

The cache ([blob::cache]) is a Remote-only mechanism: it holds re-fetchable copies of Remote blobs under storage/cache/<namespace>/… (evictable, against a per-namespace size budget — [CovenHandle::set_cache_budget]) and storage/pinned/<namespace>/… (kept). A Local blob is never in the cache, and CacheEager/CacheLazy/pin/budget describe a blob only while it is Remote. An asset (a cover, an artist image — sync::session::SyncedTable::asset) rides its subject’s gate but never keeps the subject alive.

Re-exports§

pub use rusqlite;

Structs§

ActivatedContinuation
Exact durable state required to continue an activated Store device.
AffectedRow
One table/primary-key identity affected by the shared part of a write.
BlobBody
A blob as a sized stream of already-final bytes: sealed chunks for an encrypted home, plaintext for a browsable one. Encryption-agnostic and concrete (no dyn Stream). next_part hands the bytes to a streaming upload in bounded windows so a large blob is never held whole in memory; the only collect is the single-request path for blobs at or below a provider’s multipart threshold.
BlobDecl
Where a blob-bearing table’s blob columns live, declared by the host so coven can derive every blob a row references without a runtime callback. Resolved against the live schema into a [crate::blob::decl::BlobDecls] each cycle.
BlobRef
A blob a row references: its cloud identity, encryption scope, and the two declared properties (provenance + fill). coven derives it from the row’s declared columns (crate::sync::session::BlobDecl) via [decl::BlobDecls]. Where its bytes live depends on its locality and provenance: a user-provided Local blob is the user’s file at its path; a host-provided Local blob is in coven’s local store (storage/local/<namespace>/<id>); a Remote blob’s device-local copy is a cache copy (storage/pinned/<namespace>/<locator-hash> / storage/cache/<namespace>/<locator-hash>, built from the validated namespace + exact locator hash — see [cache]).
Circle
One Circle as Circles::list reports it: its id, display name, the local identity’s role when it holds active access, and the derived state. The name is absent for a Circle with no resolved metadata (inactive, conflicted, or deleted); the role is present only when the local identity holds active roster membership.
CircleCloseParticipant
One participant in an in-flight epoch close and its slot settlement.
CircleCloseStatus
The read-only status of a Circle’s in-flight epoch close: which participant slots hold responses, exclusions, or nothing.
CircleControlCoord
Exact coordinate of one signed circle control entry.
CircleEpochCloseId
The stable identity of one Circle epoch close, derived from the durable operation that opened it. It names the close a Circles::close_status inspects and the reserved response and outcome slots that settle it; a close’s identity is fixed for its lifetime and survives cancellation and retry.
CircleId
A self-certifying 128-bit circle identity encoded as canonical lowercase base32.
CircleMemberInfo
CircleOperationId
CircleOperationInfo
CloudHomeConfig
The cloud home: which provider backs sync and its per-provider settings. One cohesive unit — connecting picks a provider and fills its fields; disconnecting resets the whole thing to default.
CloudObjectVersion
Opaque provider revision for an exact cloud object.
CloudVersionedObject
CommitFrontier
Exact materialized cut across author streams.
Config
Sync + storage configuration for one store.
DeviceActivity
Activity summary for a single remote device.
DeviceJoinAbandonment
DeviceJoinActivation
DeviceJoinCancellation
DeviceJoinCleanupActivation
DeviceJoinCleanupReceipt
DeviceJoinOffer
DeviceJoinProducerWriteRevocation
DeviceJoinReadiness
DeviceProviderAccessRequest
DeviceProviderAdmissionApproval
DeviceProviderAdmissionCompletion
DeviceRegistrationRequest
EncryptionService
Manages encryption keys and provides XChaCha20-Poly1305 encryption/decryption
FixedClock
Every now() returns the same instant.
HeldStorePosition
Hlc
Hybrid Logical Clock.
InMemoryCloudHome
In-memory CloudHome backed by a HashMap. Clone shares one backing store, so clones act as separate devices reading and writing the same cloud bucket, and a test can keep its own handle for direct at-rest assertions while each device owns a Box<dyn CloudHome> clone.
JoinedStore
JoinerJoinClosure
KeyFingerprint
Stable wire identity of one 32-byte encryption key: its full SHA-256 digest, serialized as exactly 64 lowercase hex digits.
MasterKeyring
A store’s master key material: every key it holds. This is the value custody implementations store, unlock, and re-protect — never a cipher. coven builds the EncryptionService cipher from it internally; custody never touches cipher machinery.
MemberInfo
MembershipConflictChoice
Migration
One ordered step in the host’s synced-schema ladder.
ObjectHash
OwnerRecoveryAuthority
Exact Owner grant and recovery-stream authority used to create a replacement device when no activated device continuation survives.
PendingWrite
Durable write information returned by CovenHandle::pending_writes.
ProviderAdminJoinClosure
ProviderReadyDeviceBootstrap
ProvisionalDeviceBootstrap
PublishedPosition
Exact position that made a write visible to peers.
RowBlobRef
One exact blob-bearing row version. A reference becomes stale when the live row stamp or any declared blob value changes.
RowChange
One row change extracted from a changeset.
SequentialIdProvider
Deterministic but unique: "{prefix}-0", "{prefix}-1", … Preserves the per-entity uniqueness invariant while being reproducible across runs.
SteppingClock
Advances a fixed delta per now() call: the first call returns start, the next start + step, and so on. For tests that assert ordering.
StoreBatchCommitRef
Exact identity of one signed Store commit candidate.
StoreCommitCoord
Closed coordinate of one Store commit in its author stream.
StoreCommitOrder
Predecessor and dependency order authenticated by one Store commit.
StoreDeviceId
The stable identity of one device in a Store, derived from the Store root and the device’s registration origin. It names a device across the protocol — in membership, commit authorship, and epoch-close participation — and is what Circles::exclude_close_device and Circles::close_status address.
StoreDir
Typed wrapper for a store directory path.
StoreLayout
The host’s on-disk layout for stores: where they live and what the database file is called. One rule shared by create, open, join, and restore, so a host that wants libraries/<id>/library.db instead of coven’s default stores/<id>/store.db names it once here rather than each flow hardwiring (or working around) coven’s own choice.
SyncLoopAlerts
SyncLoopSuccess
SyncedTable
A table that participates in changeset sync, declared at startup by the host and passed to [crate::CovenBuilder::synced_tables].
SystemClock
Production clock: real wall time.
Timestamp
A parsed HLC timestamp.
UpdatedAtStamper
A cloneable handle that mints _updated_at register values from a shared Hlc — the register-stamping capability, sliced off the whole [crate::sync::sync_manager::SyncManager].
UserKeypair
Ed25519 keypair for signing changesets and membership changes. The same seed can derive an X25519 keypair for key wrapping.
UuidProvider
Production provider: random v4 UUIDs.
WriteId
Stable identity of one successfully committed host transaction.
WriteReceipt
Result of one successful host transaction and its durable publication identity.
WriteRetractionWitness
Durable proof that a previously published write cannot activate.

Enums§

Audience
The one audience a synced row belongs to.
BlobCacheError
Why a blob-cache operation failed.
BlobReplacement
A blob’s replacement story: whether the row carrying it may ever be repointed at a different blob. Orthogonal to Provenance and CacheFill; a blob declares all three.
BlobScope
Which key encrypts a blob, as a host names it on a BlobRef.
CacheFill
A blob’s Remote story: how a device gets the bytes once the blob is Remote. A cache-mechanism setting — it describes a blob only while Remote — that applies to ANY blob regardless of Provenance. Orthogonal to provenance; a blob declares both.
ChangeOp
The operation type for a changeset entry.
CircleCloseSettlement
The settlement of one participant device’s create-once epoch-close response slot: it published its own applied frontier, an Owner excluded it, or the slot is still empty.
CircleInfo
One Circle as the local application sees it. A Circle with a single resolved control is Active; a Circle whose control history forked into concurrent valid successors is Conflicted and carries no name, role, or key until an Owner resolves it. A conflicted Circle refuses authoring and package publication, so it has no single resolved roster or metadata to report.
CircleOperationBlock
Why a durable Circle operation cannot currently publish. One variant per production block site; each future block site adds its own.
CircleOperationKind
CircleOperationState
CircleRole
CircleState
The public derived state of one Circle. Mapped once from the internal current state; Circles::list reports it per Circle.
CloudAccessOutcome
CloudAccessState
CloudCipher
How a cloud home protects its objects at rest. An Encrypted home seals every object under the store key (the default); a Plaintext home stores objects in the clear so the bucket is browsable, and drops the .enc suffix.
CloudHomeCredentials
Credentials for the cloud home, stored as a single JSON keyring entry.
CloudHomeError
Errors from raw cloud storage operations.
CloudHomeJoinInfo
Information needed to join a cloud home from another device.
CloudProvider
Cloud home provider selection.
ConfigError
Configuration errors.
CustomS3ExactSlots
Local operator assertion required before a custom S3 endpoint may provide exact protocol and blob slots. This is local configuration and is never accepted from invite or restore data.
DbError
An error from the owned database.
DeviceJoinAction
DeviceJoinCleanupProgress
DeviceJoinError
DeviceJoinProducer
DeviceJoinRole
DeviceJoinStatus
DeviceProviderAdmission
DeviceProviderReadiness
EncryptionError
HeldStoreCoordinate
HeldStorePositionReason
HomeStorage
How a cloud home stores its objects: opaque (encrypted, unreadable to anyone who can read the bucket) or browsable (stored in the clear at readable paths). This is not about who can reach the bucket — the storage provider’s own access control applies either way; it is about whether what they store is legible. The host picks it once, when it creates the home; it cannot change later (it determines how every object is written). One choice drives two mechanisms together:
JoinCodeError
JoinerJoinTerminal
KeyError
MemberRole
MembershipConflictInfo
MigrationStep
How a migration applies its change to the synced schema.
Provenance
A blob’s Local story: where its bytes live while the blob is Local, and whether bringing it back from Remote needs a destination path. Orthogonal to CacheFill (the Remote story) — a blob declares both.
ProviderAdminJoinTerminal
ProviderWriteAuthorityRef
RestoreAuthority
The closed authority a restore operation may exercise.
RowBlobAuthority
The authority state that determines where one row version’s blob lives. A remote-audience blob remains PendingRemote while its verified plaintext is local and no cloud object has been created; Remote carries the exact package authority needed to open its committed object.
RowIdentity
How (table, id) names one logical row across every device.
SealError
Why sealing or opening a host’s app-data failed.
WriteBlock
A semantic write fault. Retrying transport cannot change this result.
WriteResolution
WriteStatus
Current durable state of one host transaction.

Constants§

CHUNK_SIZE
64KB plaintext chunks

Traits§

BlobTransitionObserver
Notified about coven’s blob transitions, for host-specific bookkeeping and UI: per-blob upload progress while a make_remote uploads, per-blob materialize progress while a make_local copies files back, and a completion hook per direction the host turns into its own UI event.
Clock
Wall-clock source. Returns a full DateTime<Utc>; callers derive .timestamp() / .to_rfc3339() as they need.
CloudHome
DeviceJoinWriteRevocationExecutor
DeviceProviderAccessAdministrator
IdProvider
Identifier source. Yields a fresh unique id per call.
MasterKeyCustody
A store’s master keyring’s custody: who unlocks it, where a newly established or rotated one is written, and how it is removed. Implemented once per protection policy (the OS keyring, a passphrase-wrapped file, an in-memory session value, or a host’s own).
PartSink
The one per-provider streaming-upload surface: a session that accepts ordered parts and commits. The central [write_blob] driver opens one of these for a large blob and pumps BlobBody parts into it — no backend writes its own upload loop, collect, or progress call.

Functions§

decode_invite_code_info
Decode an invite code and return UI-ready info.
decode_join_request
decode_restore_code_info
Decode a restore code and return UI-ready info.

Type Aliases§

BoxPartSink
A boxed PartSink borrowing its home for 'a.
ClockRef
Shared handle to a clock. Held by Clone types (CovenHandle, CovenReadHandle) so they clone the handle, not the implementation.
IdRef
Shared handle to an id provider. Held by Clone types that need to share one id source, so they clone the handle, not the implementation.
UploadProgress
Reports how many bytes of a write have reached the backend so far. Called with the cumulative byte count as the body uploads; backends that can’t observe sub-call progress call it once at the end with the full size. The count is of the bytes handed to write (the encrypted payload).