# Identity & Networking
Mosaik's identity system is built on cryptographic keys and **intent-addressed** hashing. Every identifier in the system — networks, peers, streams, groups, collections — is a 32-byte `Digest` (blake3 hash).
Unlike content-addressed systems (Git, IPFS) where names are derived from the data itself, mosaik identifiers are derived from the *intent* — a human-readable string describing the resource's purpose. Two nodes that independently declare the same intent (e.g., `"prices"`) converge on the same identifier without any prior coordination. This makes forward references and independent declaration possible: you can name a resource before it exists.
## UniqueId: The Universal Identifier
At the core of mosaik's identity system is `Digest` — a 32-byte blake3 hash that serves as the universal identifier type:
```rust,ignore
use mosaik::Digest;
// From a string (hashes the string if not valid hex)
let id: UniqueId = "my-network".into();
// From raw bytes
let id = UniqueId::from_bytes([0u8; 32]);
// Random
let id = UniqueId::random();
// Compile-time constants via the unique_id! macro
use mosaik::unique_id;
// From a 64-char hex string (decoded directly):
const HEX_ID: UniqueId = unique_id!(
"0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef"
);
// From any arbitrary string (blake3-hashed at compile time):
const NAMED_ID: UniqueId = unique_id!("my-stream-name");
// Deterministic derivation
let derived = id.derive("sub-identifier");
```
All the following types are aliases for `Digest`:
| `UniqueId` | `Digest` | General-purpose unique identifier |
| `NetworkId` | `UniqueId` | A mosaik network (derived from name) |
| `Tag` | `UniqueId` | A capability or role label |
| `StreamId` | `UniqueId` | A data stream (derived from type name) |
| `GroupId` | `UniqueId` | A consensus group (derived from key + config) |
| `StoreId` | `UniqueId` | A replicated collection instance |
## PeerId: Node Identity
A `PeerId` is the node's public key, derived from its secret key. It's globally unique across all mosaik networks.
```rust,ignore
use mosaik::{Network, PeerId};
use iroh::SecretKey;
// Random identity (default when using Network::new)
let network = Network::new(network_id).await?;
let my_id: &PeerId = &network.local().id();
// Stable identity via explicit secret key
let secret = SecretKey::generate(&mut rand::rng());
let network = Network::builder(network_id)
.with_secret_key(secret)
.build()
.await?;
```
For bootstrap nodes and other long-lived infrastructure, you should use a fixed secret key so the node's `PeerId` (and therefore its address) remains stable across restarts.
## NetworkId: Network Isolation
A `NetworkId` is a `Digest` derived from a name string. Nodes can only connect to peers sharing the same `NetworkId`:
```rust,ignore
use mosaik::NetworkId;
// These produce the same NetworkId
let id1: NetworkId = "my-app".into();
let id2: NetworkId = "my-app".into();
assert_eq!(id1, id2);
// Different name → different network → can't communicate
let other: NetworkId = "other-app".into();
assert_ne!(id1, other);
```
The `NetworkId` also drives **automatic peer discovery**: nodes sharing the same `NetworkId` find each other through the [Mainline DHT](../subsystems/discovery/dht-bootstrap.md) without requiring any hardcoded bootstrap peers. Simply using the same network name is enough for nodes to connect.
## Tags: Capability Labels
Tags are `Digest` values used to describe a node's role or capabilities:
```rust,ignore
use mosaik::Tag;
let tag: Tag = "matcher".into();
let another: Tag = "validator".into();
```
Tags are advertised through the discovery system and can be used to filter which peers a producer accepts or which producers a consumer subscribes to:
```rust,ignore
// Only accept consumers that have the "authorized" tag
let producer = network.streams().producer::<Order>()
.require(|peer| peer.tags.contains(&"authorized".into()))
.build()?;
```
## StreamId: Stream Identity
By default, a `StreamId` is derived from the Rust type name:
```rust,ignore
use mosaik::StreamId;
// Automatically derived from the type name
let producer = network.streams().produce::<SensorReading>();
// Or set explicitly
let producer = network.streams().producer::<SensorReading>()
.with_stream_id("custom-stream-name")
.build()?;
```
## GroupId: Group Identity
A `GroupId` is deterministically derived from multiple inputs:
```text
GroupId = hash(
GroupKey,
ConsensusConfig,
StateMachine::signature(),
StateSync::signature()
)
```
This ensures that nodes with different configurations, different state machines, or different group secrets **cannot** accidentally join the same group.
## Endpoint Addresses
Nodes are addressed using `EndpointAddr` from iroh, which encodes the public key and optional relay URL. This is what you pass to bootstrap peers:
```rust,ignore
let addr = network.local().addr();
// addr contains: PeerId + relay URL + direct addresses
```