1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
//! The [efema](https://github.com/lacodda/efema) client: sync a local-first
//! app's changes between devices through a relay that cannot read them.
//!
//! An app pushes its changes into a *stream* as opaque items; every other
//! device pulls what came after its cursor, in the same order for everyone.
//! What an item means and how two changes are merged stay with the app: this
//! crate moves bytes, sealed.
//!
//! **Every entry is sealed on the device.** A [`Client`] cannot be made
//! without a [`Secret`] - the stream's passphrase or its key - and has no
//! method that sends an item as it is. The relay stores ciphertext, and so
//! does every backup of it.
//!
//! # The pieces
//!
//! - [`State`] - what a device remembers between runs: its identity, and for
//! each stream the cursor and the locked key. One file per device.
//! - [`Relay`] - the relay to talk to; it implements [`Transport`].
//! - [`Client`] - one device's view of one stream: [`push`](Client::push),
//! [`pull`](Client::pull), [`ack`](Client::ack), [`wait`](Client::wait),
//! and [`doctor`](Client::doctor) to report on all of it.
//!
//! # Keys
//!
//! The first device to open a stream creates its key - 32 random bytes - and
//! writes it to the stream locked under the passphrase (Argon2id, then
//! XChaCha20-Poly1305: [`lacodda_seal`]). Every other device finds that lock,
//! unlocks the key with the same passphrase and keeps the lock in its state,
//! so it opens without the network after that. The key itself is never
//! written anywhere unless the app asks for it with [`Client::key`].
//!
//! # Delivery
//!
//! At least once. [`Client::pull`] reads from the device's acknowledged
//! cursor and [`Client::ack`] moves it, once the app has applied what it
//! pulled - so a crash in between hands the same entries over again, and an
//! app applies an entry twice without harm.
//!
//! # Epochs
//!
//! A client writes in its app's epoch and reads up to it. When a newer
//! version of the app moves a stream to a newer epoch, an older one stops in
//! front of the first newer entry ([`Error::NewerEpoch`]) and can no longer
//! write ([`Error::EpochBehind`]) - instead of misreading the newer format or
//! mixing the older one in.
pub use ;
pub use ;
pub use ;
pub use ENTRY_OVERHEAD;
pub use Error;
pub use ;
pub use ;
pub use ;
pub use ;
/// The wire format and the hash chain, for writing a [`Transport`].
pub use ;