Kagami Mesh SDK v1.0

Don't Repeat Yourself

Or your packets. Or your keys. Or your state.

The mesh protocol that eliminates redundancy across every device in your home. One identity. One truth. Zero conflicts.

0 Platforms
0 Bit Keys
0 Conflicts
h(x)≥0 Always
write once, sync everywhere
Explore
01

Cryptographic Identity

Every device gets one key. Just one. Because if you need two, you're doing it wrong.

Ed25519: One Key to Rule Them All

Ed25519 gives you a 256-bit identity that's mathematically unique. The odds of collision? About the same as guessing a specific atom in the observable universe. Twice.

DRY Principle Applied
Your identity is computed from a single 32-byte seed. The public key? Derived. The peer ID? Derived. We don't store what we can calculate. That's DRY.
ed25519.rs
/// Generate a new random identity.
pub fn generate() -> Self {
    let signing_key = SigningKey::generate(&mut OsRng);
    Self { inner: signing_key }
}

/// Sign a message. 64 bytes of proof.
pub fn sign(&self, message: &[u8]) -> Signature {
    self.inner.sign(message)
}

/// Verify: Is this really from who they claim?
pub fn verify(
    &self,
    message: &[u8],
    signature: &Signature
) -> Result<(), IdentityError> {
    self.public_key.verify(message, signature)
}
Device Identity
Peer ID: Click to generate...
Identity Derivation
seed (32 bytes) → SecretKey → PublicKey → hex(PublicKey) = PeerID
One seed. Everything else is derived. DRY
02

End-to-End Encryption

X25519 for the handshake. XChaCha20-Poly1305 for everything after. Because repeating the key exchange for every message would be... wet.

1

Key Exchange

X25519 Diffie-Hellman

alice.dh(bob.pub) == bob.dh(alice.pub)
2

Key Derivation

HKDF-SHA256

shared → cipher_key (32 bytes)
3

Encrypt

XChaCha20-Poly1305

nonce || ciphertext || tag
x25519.rs
/// Diffie-Hellman: Same result, different inputs
pub fn diffie_hellman(
    &self,
    peer_public: &X25519PublicKey
) -> SharedSecret {
    let shared = self.inner
        .diffie_hellman(&peer_public.to_dalek());
    SharedSecret {
        bytes: shared.to_bytes()
    }
}

/// Derive encryption key from shared secret
pub fn to_cipher_key(&self) -> SecretKey {
    let key_bytes = self.derive_key(
        b"kagami-mesh-xchacha",
        32
    );
    SecretKey::from_bytes(&key_bytes)
}
xchacha.rs
/// 192-bit nonce = never repeats
pub const NONCE_SIZE: usize = 24;

/// Encrypt with random nonce prepended
pub fn encrypt(
    key: &SecretKey,
    plaintext: &[u8]
) -> Result<Vec<u8>> {
    let nonce = Nonce::generate();
    let ciphertext = cipher
        .encrypt(&nonce, plaintext)?;

    // nonce || ciphertext || tag
    let mut result = Vec::new();
    result.extend(&nonce.bytes);
    result.extend(&ciphertext);
    Ok(result)
}
Why XChaCha20-Poly1305?
  • 192-bit nonce: Random nonces without collision risk (unlike AES-GCM's 96-bit)
  • Poly1305 MAC: Authentication tag detects any tampering
  • Constant-time: No timing side-channels to exploit
  • No padding: Stream cipher = no padding oracle attacks

Live Encryption Demo

Generate keys first...
Shared Key: Not generated
03

Conflict-Free Synchronization

Vector Clocks track causality. CRDTs resolve conflicts automatically. Because "last write wins" is a terrible strategy when you have 6 devices.

Vector Clock

Happens-before ordering without synchronized clocks

{ "hub": 5, "phone": 3, "watch": 2 }

G-Counter

Distributed counting that only grows

sum(all_nodes) = total

LWW-Register

Last-writer-wins with timestamps

max(timestamp) = winner

OR-Set

Add and remove without conflicts

unique_tags = no conflicts

Vector Clock: Time Without Time

Wall clocks lie. Network delays exist. But Vector Clocks don't care. They track causality, not time.

vector_clock.rs
/// Compare: Who happened first?
pub fn compare(&self, other: &VectorClock)
    -> VectorClockOrdering
{
    match (self_less, other_less) {
        (false, false) => Equal,
        (true, false) => HappensBefore,
        (false, true) => HappensAfter,
        (true, true) => Concurrent,
    }
}

/// Merge: Take max of each node
pub fn merge(&mut self, other: &VectorClock) {
    for (node_id, &value) in &other.clocks {
        self.clocks
            .entry(node_id)
            .and_modify(|v| *v = max(*v, value))
            .or_insert(value);
    }
}

CRDTs: Math Beats Coordination

Why have a leader resolve conflicts when math can do it? CRDTs merge deterministically. Same inputs = same result. Every. Single. Time.

crdt.rs
/// OR-Set: Add with unique tag
pub fn add(&mut self, value: T, node_id: &str) {
    let tag = self.generate_tag(node_id);
    self.elements.insert(OrSetElement {
        value,
        tag  // "node1:42" - unique!
    });
}

/// Remove: Only removes YOUR adds
pub fn remove(&mut self, value: &T) {
    let tags: Vec<String> = self.elements
        .iter()
        .filter(|e| &e.value == value)
        .map(|e| e.tag.clone())
        .collect();

    for tag in tags {
        self.tombstones.insert(tag);
    }
}
DRY Principle Applied
Traditional sync: Write logic for every conflict scenario.
CRDT sync: a.merge(b).

We wrote the merge logic once. It handles all conflicts. DRY

Live Sync Demo

Phone
{ "phone": 0 }
Hub
{ "hub": 0 }
Merged Clock: { "phone": 0, "hub": 0 }
04

Mesh Topology

Hub as coordinator. Mobile as nodes. Desktop as workstation. All speaking the same protocol via UniFFI bindings.

UniFFI: Write Once, Bind Everywhere

The Rust SDK compiles to native binaries. UniFFI generates bindings. iOS, Android, Desktop - all using the same cryptographic code.

kagami-mesh-sdk (Rust) uniffi::setup_scaffolding!()
.swift .kt .rs
DRY Principle Applied
Without UniFFI: Write Ed25519 in Swift. Write Ed25519 in Kotlin. Write Ed25519 in Rust. Debug three implementations.
With UniFFI: Write Ed25519 in Rust. Generate the rest. Sleep well at night.

Same cryptographic guarantees. One implementation. Zero bugs duplicated. DRY

Voice Processing

Speech recognition written once. Running everywhere. That's the whole point.

500ms. Not 500ms × 6.

Context Sync

State duplicated automatically, so you don't have to. Merge logic: written once.

∞ devices, 1 truth

Offline-First

Your network code, written once. Your users' frustration, eliminated everywhere.

1 pattern, 0 cascades
05

Circuit Breaker

Networks fail. The question is: do you fail gracefully or hammer a dead server?

circuit_breaker.rs
/// Check if a request should be allowed
pub fn allow_request(&self) -> bool {
    match self.state() {
        CircuitState::Closed => true,
        CircuitState::Open => {
            // Check if reset timeout has elapsed
            if time_since_failure > RESET_TIMEOUT {
                self.set_state(HalfOpen);
                true
            } else {
                false  // Fail fast!
            }
        }
        CircuitState::HalfOpen => true,
    }
}

/// Pattern: Closed → Open → HalfOpen → Closed
/// h(x) >= 0. Always.
DRY Principle Applied
Every platform needs resilient networking. Every platform needs the same pattern.
We wrote CircuitBreaker once in Rust.
iOS, Android, Desktop, watchOS, visionOS - all use the same implementation.

One circuit breaker. Six platforms. Zero repeated bugs. DRY
06

Live Demo

Watch the mesh in action. Every node. Every message. Every sync.

Interactive mesh network demonstration
00:00:00 Mesh initialized. Hub online.

Protocol Stack Summary

Layer Technology Purpose DRY Factor
Identity Ed25519 Sign & verify 1 seed → all keys
Key Exchange X25519 Shared secret 1 exchange → all messages
Encryption XChaCha20-Poly1305 Confidentiality 1 impl → 6 platforms
Causality VectorClock Ordering 1 merge → ∞ nodes
State CRDTs Consistency 1 merge → 0 conflicts
Resilience CircuitBreaker Graceful degradation 1 pattern → 0 cascades