# How to Set Up Peer Mesh Communication in Apache Maka

> Learn to set up Peer Mesh communication in Apache Maka for secured, decentralized host discovery. Join via invitations and maintain synchronized state easily.

- Repository: [The Apache Software Foundation/maka](https://github.com/apache/maka)
- Tags: how-to-guide
- Published: 2026-09-09

---

**Maka’s Peer Mesh enables cryptographically secured, decentralized host discovery through an authority node that signs rosters and reachability leases, allowing members to join via consumable invitations and maintain synchronized state through periodic reconciliation.**

Setting up Peer Mesh communication in Apache Maka establishes a secure, distributed topology where runtime-host instances discover each other and exchange signed advertisements. This guide walks through the complete implementation using the source code from the `apache/maka` repository, referencing the exact APIs and file paths used in production.

## Core Concepts of Peer Mesh

Maka’s Peer Mesh operates on three fundamental primitives defined in [`packages/runtime-host/src/peer-mesh/model.js`](https://github.com/apache/maka/blob/main/packages/runtime-host/src/peer-mesh/model.js) and [`packages/runtime-host/src/peer-reachability/index.js`](https://github.com/apache/maka/blob/main/packages/runtime-host/src/peer-reachability/index.js).

### Authority Node

The **authority node** acts as the cryptographic owner of the mesh. It generates the mesh ID, signs the roster, and issues reachability leases. The `authorityPrivateKey` never leaves the authority node and is exclusively used to sign new rosters and authorize members.

### Member Nodes

**Member nodes** are hosts or clients that join the mesh by consuming signed invitations. Once admitted, they hold reachability leases describing network paths (e.g., via relays) and synchronize state with the authority through reconciliation.

### Reachability Leases

These are **signed tokens** with automatic refresh logic enforced in [`packages/runtime-host/src/peer-reachability/index.js`](https://github.com/apache/maka/blob/main/packages/runtime-host/src/peer-reachability/index.js). Each lease includes TTL, clock skew validation, and refresh lead times. Members must maintain valid leases to remain reachable in the mesh.

## Step-by-Step Implementation Guide

Follow these steps derived from [`packages/runtime-host/src/__tests__/peer-mesh.test.ts`](https://github.com/apache/maka/blob/main/packages/runtime-host/src/__tests__/peer-mesh.test.ts) to configure your nodes.

### 1. Create a Transport Implementation

Instantiate a transport satisfying the `PeerMeshTransport` interface. For testing, use `MemoryPeerNetwork` from the testing utilities. Production deployments require a custom transport implementation handling control messages and lease exchanges.

```typescript
import { MemoryPeerNetwork } from '@maka/runtime-host/testing';

const network = new MemoryPeerNetwork();
const authorityPeer = network.create('peer-a');
const memberPeerB = network.create('peer-b');
const memberPeerC = network.create('peer-c');

```

### 2. Open Peer Mesh Nodes

Use `openPeerMeshNode` from [`packages/runtime-host/src/peer-mesh/node.js`](https://github.com/apache/maka/blob/main/packages/runtime-host/src/peer-mesh/node.js) to initialize each participant. The function requires a persistent `dataRoot`, a transport client exposing `useClock`, and an `endpointKind` (`'client'` for authority, `'host'` for members).

```typescript
import { openPeerMeshNode } from '@maka/runtime-host/peer-mesh/node';
import { mkdtemp, rm } from 'node:fs/promises';
import { tmpdir } from 'node:os';
import { join } from 'node:path';

const root = await mkdtemp(join(tmpdir(), 'maka-peer-mesh-'));

const authority = await openPeerMeshNode({
  dataRoot: join(root, 'authority'),
  peer: authorityPeer,
  endpointKind: 'client',
});

const memberB = await openPeerMeshNode({
  dataRoot: join(root, 'member-b'),
  peer: memberPeerB,
  endpointKind: 'host',
});

const memberC = await openPeerMeshNode({
  dataRoot: join(root, 'member-c'),
  peer: memberPeerC,
  endpointKind: 'host',
});

```

### 3. Create the Mesh

The authority generates a unique mesh ID and signed roster by calling `authority.create()`. This utilizes `generatePeerMeshAuthorityKeyPair` and `signPeerMeshRoster` from [`packages/runtime-host/src/peer-mesh/model.js`](https://github.com/apache/maka/blob/main/packages/runtime-host/src/peer-mesh/model.js).

```typescript
await authority.setDisplayName('Alice Desktop');
const mesh = await authority.create();
const meshId = mesh.roster.roster.meshId;
console.log('Mesh ID:', meshId);

```

### 4. Serve and Invite Members

Start the authority service with `authority.serve()` to accept control connections. Issue consumable invitations via `authority.invite(meshId)`. Each invitation is single-use; the first successful `member.join(invitation)` consumes it, requiring fresh invitations for subsequent members.

```typescript
const serving = authority.serve();

// First member
const invitation = await authority.invite(meshId);
await memberB.join(invitation);

// Second member requires new invitation
const secondInvite = await authority.invite(meshId);
await memberC.join(secondInvite);

```

### 5. Synchronize State

Call `node.reconcile()` to pull the latest signed roster and verify reachability leases. This enforces cryptographic signature validation and TTL checks defined in [`packages/runtime-host/src/peer-reachability/index.js`](https://github.com/apache/maka/blob/main/packages/runtime-host/src/peer-reachability/index.js).

```typescript
await memberB.reconcile();
await memberC.reconcile();

```

### Complete Runnable Example

The following implementation combines all steps using the in-memory transport, matching the validation logic in the official test suite:

```typescript
import { mkdtemp, rm } from 'node:fs/promises';
import { tmpdir } from 'node:os';
import { join } from 'node:path';
import { MemoryPeerNetwork } from '@maka/runtime-host/testing';
import { openPeerMeshNode } from '@maka/runtime-host/peer-mesh/node';

// Setup workspace and network
const root = await mkdtemp(join(tmpdir(), 'maka-peer-mesh-'));
const network = new MemoryPeerNetwork();
const [authorityPeer, memberPeerB, memberPeerC] = 
  ['peer-a', 'peer-b', 'peer-c'].map(id => network.create(id));

// Initialize nodes
const authority = await openPeerMeshNode({
  dataRoot: join(root, 'authority'),
  peer: authorityPeer,
  endpointKind: 'client',
});

const memberB = await openPeerMeshNode({
  dataRoot: join(root, 'member-b'),
  peer: memberPeerB,
  endpointKind: 'host',
});

const memberC = await openPeerMeshNode({
  dataRoot: join(root, 'member-c'),
  peer: memberPeerC,
  endpointKind: 'host',
});

// Create mesh
await authority.setDisplayName('Alice Desktop');
const mesh = await authority.create();
console.log('Mesh ID:', mesh.roster.roster.meshId);

// Serve and invite
const serving = authority.serve();
const invitation = await authority.invite(mesh.roster.roster.meshId);
await memberB.join(invitation);

const secondInvite = await authority.invite(mesh.roster.roster.meshId);
await memberC.join(secondInvite);

// Synchronize
await memberB.reconcile();
await memberC.reconcile();

// Cleanup
await Promise.all([
  authority.close(),
  memberB.close(),
  memberC.close(),
  serving,
  rm(root, { recursive: true, force: true })
]);

```

## Managing the Mesh Lifecycle

After you set up Peer Mesh communication in Maka, use authority-only methods from [`packages/runtime-host/src/server/peer-mesh-authority.js`](https://github.com/apache/maka/blob/main/packages/runtime-host/src/server/peer-mesh-authority.js) to manage the deployment.

### Rename the Mesh

Update the display name and propagate changes through reconciliation:

```typescript
await authority.setMeshDisplayName(mesh.roster.roster.meshId, 'Release Team');
await memberB.reconcile();  // Member now sees updated name

```

### Remove Members

Evict a specific peer by ID:

```typescript
await authority.remove(mesh.roster.roster.meshId, 'peer-b');
await memberC.reconcile();  // Remaining members see updated roster

```

### Close the Mesh

Permanently terminate the mesh, signaling all members:

```typescript
await authority.closeMesh(mesh.roster.roster.meshId);
await authority.reconcile();
await memberC.reconcile();  // Member observes closed flag and exits

```

## Security Architecture

The Peer Mesh security model relies on cryptographic signatures implemented in [`packages/runtime-host/src/peer-mesh/model.js`](https://github.com/apache/maka/blob/main/packages/runtime-host/src/peer-mesh/model.js). All roster updates and reachability leases are signed by the authority; members verify these signatures during `reconcile()`. The authority’s private key never appears on member nodes, ensuring a compromised member cannot forge mesh updates or impersonate the authority.

Persistence is handled by [`packages/runtime-host/src/peer-mesh/store.js`](https://github.com/apache/maka/blob/main/packages/runtime-host/src/peer-mesh/store.js), which detects corruption via `PeerMeshPersistenceError` and handles commit outcomes through `PeerMeshPostCommitError`.

## Key Source Files Reference

- **[`packages/runtime-host/src/peer-mesh/model.js`](https://github.com/apache/maka/blob/main/packages/runtime-host/src/peer-mesh/model.js)** – Defines `peerMeshId`, roster structures, and cryptographic helpers including `generatePeerMeshAuthorityKeyPair`, `signPeerMeshRoster`, and `decodeSignedPeerMeshRoster`.

- **[`packages/runtime-host/src/peer-mesh/node.js`](https://github.com/apache/maka/blob/main/packages/runtime-host/src/peer-mesh/node.js)** – Implements `openPeerMeshNode` and the `PeerMeshNode` class managing the complete node lifecycle: create, join, leave, reconcile, and close.

- **[`packages/runtime-host/src/peer-mesh/store.js`](https://github.com/apache/maka/blob/main/packages/runtime-host/src/peer-mesh/store.js)** – Handles persistent storage of mesh state with corruption detection and unrecoverable commit handling.

- **[`packages/runtime-host/src/peer-reachability/index.js`](https://github.com/apache/maka/blob/main/packages/runtime-host/src/peer-reachability/index.js)** – Validates reachability leases, enforces TTL expiration, and manages clock skew tolerance.

- **[`packages/runtime-host/src/server/peer-mesh-authority.js`](https://github.com/apache/maka/blob/main/packages/runtime-host/src/server/peer-mesh-authority.js)** – Provides RPC operation handlers (`peer.mesh.create`, `peer.mesh.reconcile`) exposing mesh management to remote peers.

- **[`packages/runtime-host/src/__tests__/peer-mesh.test.ts`](https://github.com/apache/maka/blob/main/packages/runtime-host/src/__tests__/peer-mesh.test.ts)** – End-to-end test suite demonstrating authority creation, multi-member onboarding, invitation edge cases, and lease refreshes.

## Summary

- **Transport Layer**: Implement `PeerMeshTransport` or use `MemoryPeerNetwork` for testing to enable inter-node communication.
- **Node Initialization**: Call `openPeerMeshNode()` with `dataRoot`, transport client, and `endpointKind` to instantiate authority or member nodes.
- **Mesh Creation**: Authority calls `create()` to generate cryptographically signed rosters and unique mesh IDs.
- **Member Onboarding**: Issue single-use invitations via `invite()` and confirm with `join()`; each invitation supports exactly one member.
- **State Synchronization**: Use `reconcile()` to enforce signed roster consistency and reachability lease validity across all nodes.
- **Lifecycle Management**: Authority exclusively controls renaming, member removal, and mesh closure, with all changes signed and propagated through reconciliation.

## Frequently Asked Questions

### What transport implementation should I use for production Maka deployments?

For production, implement the `PeerMeshTransport` interface with a real network layer instead of `MemoryPeerNetwork`. The transport must support control messages and reachability lease exchanges as consumed by `openPeerMeshNode`. The in-memory implementation serves exclusively for unit testing in [`packages/runtime-host/src/__tests__/peer-mesh.test.ts`](https://github.com/apache/maka/blob/main/packages/runtime-host/src/__tests__/peer-mesh.test.ts).

### Why do I need a new invitation for each member joining the mesh?

Invitations are **consumable single-use tokens**. When `authority.invite()` generates an invitation, it creates a signed reachability lease consumed by the first successful `member.join()` call. This design prevents replay attacks and ensures the authority maintains strict cryptographic control over mesh membership. Subsequent joins require fresh invitations.

### How does Maka handle clock skew between authority and member nodes?

Clock skew is enforced in [`packages/runtime-host/src/peer-reachability/index.js`](https://github.com/apache/maka/blob/main/packages/runtime-host/src/peer-reachability/index.js) during lease validation. Reachability leases include TTL and refresh lead times; `reconcile()` verifies these timestamps against the peer's clock. Significant clock divergence causes lease rejection, preventing stale or premature reachability claims.

### Can I recover a mesh if the authority node loses its data?

No. The authority's private key (`authorityPrivateKey`) and mesh state are stored exclusively in the authority's `dataRoot` directory managed by [`packages/runtime-host/src/peer-mesh/store.js`](https://github.com/apache/maka/blob/main/packages/runtime-host/src/peer-mesh/store.js). Loss of this persistent storage without backup results in irrecoverable loss of mesh control, as the cryptographic keys required to sign new rosters cannot be regenerated.