mosaik 0.3.13

A Rust runtime for building self-organizing, leaderless distributed systems.
Documentation
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
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
# Primitives Reference

This chapter documents the foundational types and utilities that the rest of
mosaik builds on. These live in the `primitives` module (public types) and
internal helpers.

## `Digest` / `UniqueId` / `Tag`

The core identifier type — a 32-byte blake3 hash.

```rust,ignore
use mosaik::Digest;  // re-exported at crate root
```

`Digest`, `UniqueId`, and `Tag` are all the same type, aliased for clarity in
different contexts:

| Alias       | Used for                                   |
| ----------- | ------------------------------------------ |
| `Digest`    | General-purpose 32-byte identifier         |
| `UniqueId`  | Derived identity (groups, stores, bonds)   |
| `Tag`       | Discovery tags for peer classification     |
| `NetworkId` | Network identifier (`= Digest`)            |
| `GroupId`   | Group identifier (`= Digest`)              |
| `StreamId`  | Stream identifier (`= Digest`)             |
| `StoreId`   | Collection store identifier (`= UniqueId`) |

### Construction

```rust,ignore
// From a string (hashes the string with blake3)
let tag = Digest::from("validator");

// From a hex string (64 chars = direct decode, otherwise hashed)
let id = Digest::from("a1b2c3d4...");

// From numeric types (little-endian encoded, then hashed)
let id = Digest::from_u64(42);

// From multiple parts (concatenated, then hashed)
let id = Digest::from_parts(&["prefix", "suffix"]);

// Derive a child ID deterministically
let child = parent.derive("child-name");

// Random
let id = Digest::random();

// Zero (sentinel value)
let zero = Digest::zero();
```

### Compile-time construction

Two equivalent macros are available — `id!` is the short alias:

```rust,ignore
use mosaik::{id, unique_id};

const MY_ID: UniqueId = id!("a1b2c3d4e5f6...");         // 64-char hex literal
const MY_ID: UniqueId = unique_id!("a1b2c3d4e5f6...");  // identical, longer name
```

Both accept either a 64-character hex string (decoded directly) or any other
string (hashed with blake3).

#### `id!` vs `unique_id!`

The `id!` macro is a short alias for `unique_id!` — both produce a compile-time
`UniqueId` from a string literal. Use whichever reads more naturally.

### Display

- `Display` — short hex (first 5 bytes): `a1b2c3d4e5`
- `Debug` — full 64-character hex string
- `Short<T>` wrapper — always shows first 5 bytes
- `Abbreviated<const LEN, T>` — shows `first..last` if longer than LEN

### Serialization

- **Human-readable** formats (JSON, TOML): hex string
- **Binary** formats (postcard): raw 32 bytes

---

## `Ticket`

An opaque, typed credential that peers attach to their discovery entry for
authorization purposes. Ticket types live in the `mosaik::tickets` module.

```rust,ignore
use mosaik::{tickets::Ticket, UniqueId, id, Bytes};

const MY_AUTH: UniqueId = id!("my-app.auth");

let ticket = Ticket::new(MY_AUTH, Bytes::from("credential-data"));
let id: UniqueId = ticket.id(); // deterministic, derived from class + data
```

| Field   | Type       | Description                                    |
| ------- | ---------- | ---------------------------------------------- |
| `class` | `UniqueId` | Identifies the authorization scheme            |
| `data`  | `Bytes`    | Opaque payload; format determined by the class |

Tickets are stored in a peer's `PeerEntry` and propagated via gossip and
catalog sync. The discovery system never interprets ticket data --
validation is done via `TicketValidator` implementations or `require`
closures.

The `mosaik::tickets` module also provides:

- **`Jwt`** — built-in JWT validator supporting HS256/384/512,
  ES256/256K/384/512, and EdDSA.
- **`JwtTicketBuilder`** — signs and issues JWT tickets for peers.
- **`TicketValidator`** trait — implement for custom credential schemes.
- Algorithm-specific key types (`Hs256`, `Es256`, `Es256SigningKey`,
  `EdDsa`, `EdDsaSigningKey`, etc.).

See [Discovery > Auth Tickets](../subsystems/discovery/tickets.md) for
a full walkthrough.

---

## `PeerId`

```rust,ignore
type PeerId = iroh::EndpointId;
```

A peer's public identity, derived from their Ed25519 public key. This is an
iroh type, not a mosaik `Digest`. It is used in discovery, bonds, and
connection authentication.

## `SecretKey`

Re-exported from iroh. An Ed25519 secret key that determines a node's
`PeerId`. If not provided to `NetworkBuilder`, a random key is generated
automatically — this is the recommended default for regular nodes.

Specifying a fixed secret key is only recommended for **bootstrap nodes**
that need a stable, well-known peer ID across restarts:

```rust,ignore
use mosaik::SecretKey;

// Auto-generated (default) — new identity each run
let network = Network::builder()
    .network_id("my-network")
    .build().await?;

// Fixed key — stable identity, recommended only for bootstrap nodes
let key = SecretKey::generate(&mut rand::rng());
let bootstrap = Network::builder()
    .network_id("my-network")
    .secret_key(key)
    .build().await?;
```

---

## The `collection!` macro

The recommended way to declare named collection definitions. It generates a
struct with a compile-time `StoreId` and implements `CollectionReader` and/or
`CollectionWriter`.

```rust,ignore
use mosaik::collection;

// Full (reader + writer)
collection!(pub Prices = mosaik::collections::Map<String, f64>, "prices");

// Reader only
collection!(pub reader Prices = mosaik::collections::Map<String, f64>, "prices");

// Writer only
collection!(pub writer Prices = mosaik::collections::Map<String, f64>, "prices");

// With generics
collection!(pub Items<T> = mosaik::collections::Vec<T>, "app.items");
```

The store ID string is **intent-addressed** — hashed with blake3 at compile
time (or decoded directly if it is exactly 64 hex characters). Two nodes that
independently declare the same string converge on the same `StoreId` without
coordination.

See [Collections > collection! macro](../subsystems/collections.md#the-collection-macro-recommended)
for the full syntax reference, mode table, and usage examples.

## Collection traits and type aliases

These traits and aliases work with types generated by the `collection!` macro.
The traits live in `mosaik::collections`; the type aliases are re-exported at
the crate root.

| Item               | Kind       | Description                                                     |
| ------------------ | ---------- | --------------------------------------------------------------- |
| `CollectionReader` | Trait      | Provides `fn reader(&Network)` and `fn online_reader(&Network)` |
| `CollectionWriter` | Trait      | Provides `fn writer(&Network)` and `fn online_writer(&Network)` |
| `ReaderOf<C>`      | Type alias | `<C as CollectionReader>::Reader` — the concrete reader         |
| `WriterOf<C>`      | Type alias | `<C as CollectionWriter>::Writer` — the concrete writer         |

The `online_reader` and `online_writer` methods create the handle and await
`.when().online()` in a single call, reducing the common two-step pattern.

```rust,ignore
use mosaik::{collection, collections::CollectionReader, ReaderOf};

collection!(pub MyVec = mosaik::collections::Vec<String>, "my.vec");

// ReaderOf<MyVec> resolves to VecReader<String>
let reader: ReaderOf<MyVec> = MyVec::reader(&network);
```

## The `stream!` macro

The recommended way to declare named stream definitions. It generates a
struct with a compile-time `StreamId` and implements `StreamProducer`
and/or `StreamConsumer`.

```rust,ignore
use mosaik::stream;

// Type-derived StreamId (most common)
stream!(pub PriceFeed = PriceUpdate);

// Explicit StreamId
stream!(pub PriceFeed = PriceUpdate, "oracle.price");

// Producer only
stream!(pub producer PriceFeed = PriceUpdate, "oracle.price");

// Consumer only
stream!(pub consumer PriceFeed = PriceUpdate, "oracle.price");

// With configuration
stream!(pub PriceFeed = PriceUpdate, "oracle.price",
    producer require: |peer| peer.tags().contains(&tag!("trusted")),
    producer online_when: |c| c.minimum_of(2),
    consumer require: |peer| true,
);
```

The stream ID string is **intent-addressed** — hashed with blake3 at compile
time (or decoded directly if it is exactly 64 hex characters). When omitted,
the `StreamId` is derived from the datum type name. Two nodes that
independently declare the same string converge on the same `StreamId` without
coordination.

See [Streams > stream! macro](../subsystems/streams.md#the-stream-macro-recommended)
for the full syntax reference, configuration keys, and usage examples.

## Stream traits and type aliases

These traits and aliases work with types generated by the `stream!` macro.
The traits live in `mosaik::streams`; the type aliases are re-exported at
the crate root.

| Item             | Kind       | Description                                                         |
| ---------------- | ---------- | ------------------------------------------------------------------- |
| `StreamProducer` | Trait      | Provides `fn producer(&Network)` and `fn online_producer(&Network)` |
| `StreamConsumer` | Trait      | Provides `fn consumer(&Network)` and `fn online_consumer(&Network)` |
| `ProducerOf<S>`  | Type alias | `<S as StreamProducer>::Producer` — the concrete producer           |
| `ConsumerOf<S>`  | Type alias | `<S as StreamConsumer>::Consumer` — the concrete consumer           |

The `online_producer` and `online_consumer` methods create the handle and
await `.when().online()` in a single call, reducing the common two-step
pattern.

```rust,ignore
use mosaik::{stream, streams::StreamProducer, ProducerOf};

stream!(pub PriceFeed = PriceUpdate, "oracle.price");

// ProducerOf<PriceFeed> resolves to Producer<PriceUpdate>
let producer: ProducerOf<PriceFeed> = PriceFeed::producer(&network);
```

## Stream definitions (`ProducerDef` / `ConsumerDef`)

> **Note:** The [`stream!` macro]#the-stream-macro is now the
> recommended approach. `ProducerDef` and `ConsumerDef` still work and
> are useful when you need an explicit definition value.

These types allow you to define a stream's identity at compile time and
create pre-configured builders from it. They live in `mosaik::streams`.

| Type             | Description                                      |
| ---------------- | ------------------------------------------------ |
| `ProducerDef<T>` | Producer definition — creates a producer builder |
| `ConsumerDef<T>` | Consumer definition — creates a consumer builder |

```rust,ignore
use mosaik::{unique_id, streams::ProducerDef};

const PRICES: ProducerDef<PriceUpdate> =
    ProducerDef::new(Some(unique_id!("prices")));

let producer = PRICES.open(&network).build()?;
```

| Method                           | Available on | Returns |
| -------------------------------- | ------------ | ------- |
| `const fn new(Option<StreamId>)` | Both types   | `Self`  |
| `fn open(&self, &Network)`       | Both types   | Builder |

---

## Collection definitions (`CollectionDef`)

> **Note:** The [`collection!` macro]#the-collection-macro is now the
> recommended approach. `CollectionDef`, `ReaderDef`, and `WriterDef` still
> work and are useful when you need an explicit definition value.

These types allow you to define a collection's identity at compile time and
create readers or writers from it. They live in `mosaik::collections`.

| Type                | Description                                                            |
| ------------------- | ---------------------------------------------------------------------- |
| `CollectionDef<C>`  | Full definition — can create both writers and readers for collection C |
| `ReaderDef<C>`      | Reader-only definition — typically exported by library authors         |
| `WriterDef<C>`      | Writer-only definition                                                 |
| `CollectionFromDef` | Trait implemented for all collection types; associates Reader/Writer   |

The type parameter `C` is the collection type (e.g., `Map<String, u64>`) and
`T` encodes the value types as a tuple (`(String, u64)` for Map, `T` directly
for single-type collections like `Vec<T>`).

```rust,ignore
use mosaik::{unique_id, collections::{CollectionDef, ReaderDef, Map}};

const MY_MAP: CollectionDef<Map<String, u64>> =
	CollectionDef::new(unique_id!("my-map"));

const MY_MAP_READER: ReaderDef<Map<String, u64>> =
	MY_MAP.as_reader();
```

| Method                       | Available on                 | Returns     |
| ---------------------------- | ---------------------------- | ----------- |
| `const fn new(StoreId)`      | All three types              | `Self`      |
| `const fn as_reader(&self)`  | `CollectionDef`              | `ReaderDef` |
| `const fn as_writer(&self)`  | `CollectionDef`              | `WriterDef` |
| `fn reader(&self, &Network)` | `CollectionDef`, `ReaderDef` | `C::Reader` |
| `fn writer(&self, &Network)` | `CollectionDef`, `WriterDef` | `C::Writer` |

See [Collections > CollectionDef](../subsystems/collections.md#collection-definitions-collectiondef)
for usage examples and the full type-parameter mapping table.

---

## Wire encoding

All network messages use **postcard** — a compact, `#[no_std]`-compatible
binary format using variable-length integers.

| Function                                                          | Description                            |
| ----------------------------------------------------------------- | -------------------------------------- |
| `serialize<T: Serialize>(&T) -> Bytes`                            | Serialize to bytes (panics on failure) |
| `deserialize<T: DeserializeOwned>(impl AsRef<[u8]>) -> Result<T>` | Deserialize from bytes                 |

These are internal crate functions. Application code interacts with them
indirectly through `Link<P>` send/receive and collection operations.

---

## `Bytes` / `BytesMut`

Re-exported from the `bytes` crate. Used throughout mosaik for zero-copy
byte buffers:

```rust,ignore
use mosaik::Bytes;

let data: Bytes = serialize(&my_message);
```

---

## `BackoffFactory`

A factory type for creating retry backoff strategies:

```rust,ignore
type BackoffFactory = Arc<
    dyn Fn() -> Box<dyn Backoff + Send + Sync + 'static>
        + Send + Sync + 'static
>;
```

Used in `streams::Config` to configure consumer reconnection. The `backoff`
crate is re-exported at `mosaik::streams::backoff`.

---

## Formatting utilities

Internal helpers for consistent debug output:

| Type                        | Description                                          |
| --------------------------- | ---------------------------------------------------- |
| `Pretty<T>`                 | Pass-through wrapper (for trait integration)         |
| `Short<T>`                  | Display first 5 bytes as hex                         |
| `Abbreviated<const LEN, T>` | Show `first..last` hex if longer than LEN bytes      |
| `Redacted<T>`               | Always prints `<redacted>`                           |
| `FmtIter<W, I>`             | Format iterator elements comma-separated in brackets |

---

## `IntoIterOrSingle<T>`

An ergonomic trait that lets API methods accept either a single item or an
iterator:

```rust,ignore
// Both work:
discovery.with_tags("validator");            // single tag
discovery.with_tags(["validator", "relay"]); // multiple tags
```

This is implemented via two blanket impls using `Variant<0>` (single item
via `Into<T>`) and `Variant<1>` (iterator of `Into<T>`).

---

## Internal async primitives

These are `pub(crate)` and not part of the public API, but understanding them
helps when reading mosaik's source code.

### `UnboundedChannel<T>`

A wrapper around `tokio::sync::mpsc::unbounded_channel` that keeps both the
sender and receiver in one struct:

```rust,ignore
let channel = UnboundedChannel::new();
channel.send(42);
let val = channel.recv().await;
```

| Method                           | Description                     |
| -------------------------------- | ------------------------------- |
| `sender()`                       | Get `&UnboundedSender<T>`       |
| `receiver()`                     | Get `&mut UnboundedReceiver<T>` |
| `send(T)`                        | Send (errors silently ignored)  |
| `recv()`                         | Async receive                   |
| `poll_recv(cx)`                  | Poll-based receive              |
| `poll_recv_many(cx, buf, limit)` | Batch poll receive              |
| `is_empty()` / `len()`           | Queue inspection                |

### `AsyncWorkQueue<T>`

A `FuturesUnordered` wrapper with a permanently-pending sentinel future so
that polling never returns `None`:

```rust,ignore
let queue = AsyncWorkQueue::new();
queue.enqueue(async { do_work().await });

// Poll via Stream trait — never completes while empty
while let Some(result) = queue.next().await {
    handle(result);
}
```

### `BoxPinFut<T>`

Type alias for boxed, pinned, send futures:

```rust,ignore
type BoxPinFut<T> = Pin<Box<dyn Future<Output = T> + Send + 'static>>;
```

The `InternalFutureExt` trait adds a `.pin()` method to any
`Future + Send + 'static` for ergonomic boxing.