# BLE Components in the V3 Architecture: How Bitchat Structures Its Bluetooth Stack

> Explore the BLE components in Bitchat's V3 architecture. Understand how BLELinkLayer, Mesh Engine, Feature Modules, and App Boundary ensure deadlock free deterministic mesh networking.

- Repository: [permissionlesstech/bitchat](https://github.com/permissionlesstech/bitchat)
- Tags: architecture
- Published: 2026-08-23

---

**The Bitchat V3 BLE stack organizes functionality into four distinct layers—BLELinkLayer, Mesh Engine, Feature Modules, and App Boundary—that enforce strict concurrency contracts to eliminate deadlocks and enable deterministic mesh networking.**

The `permissionlesstech/bitchat` repository implements a complete redesign of its Bluetooth Low Energy transport in the V3 architecture. This clean, layered approach separates radio-level operations from protocol logic, with each BLE component managing isolated state and communicating through well-defined interfaces. Understanding these boundaries is essential for developers extending the mesh protocol or optimizing connection handling.

## The Four Core BLE Components

The V3 architecture divides responsibilities across four major components, each owning a distinct slice of state and behavior.

### BLELinkLayer: Low-Level Radio Management

**BLELinkLayer** serves as the low-level link layer that directly interacts with CoreBluetooth. This component owns all scanning and advertising logic, duty-cycle scheduling, connection handling, MTU negotiation, and back-pressure buffers for writes and notifications. It also manages state restoration and communicates upward via `LinkEvent` and downward via `LinkCommand`. According to the architecture documentation, this layer confines all CoreBluetooth objects and timing-sensitive operations to the `bleQueue`.

### Mesh Engine: Protocol State and Logic

The **Mesh Engine** operates as a single-writer serial queue that houses the entire mesh protocol state. It handles packet encoding and decoding, fragmentation, duplicate-packet deduplication, relay policies, and the peer registry. The engine also manages topology-gossip synchronization and Noise protocol orchestration. Pure-policy satellites plug into this engine unchanged, keeping the core free of feature-specific logic.

### Feature Modules: Self-Contained Capabilities

**Feature Modules** represent self-contained units such as courier, board, pre-keys, private media, file transfer, voice, diagnostics, groups, and verification/vouch systems. Each module owns its own state and registers for specific message types, ensuring the engine remains free of feature-specific logic. This modularity allows new capabilities to be added without modifying the underlying mesh protocol.

### App Boundary (Transport Core)

The **App Boundary**, also referred to as the **Transport Core**, acts as a small façade exposing a uniform `Transport` protocol to the rest of the application. It delegates concrete BLE work to the mesh engine and discovers additional capabilities through optional casting (e.g., `MeshBridgingTransport`, `PanicResettingTransport`, `BluetoothStateReporting`). This abstraction prevents the UI and business layers from depending on implementation details of the BLE stack.

## Supporting Infrastructure and State Management

Beyond the high-level layers, several concrete BLE service files implement detailed state management responsibilities:

### BLELinkStateStore.swift

[`BLELinkStateStore.swift`](https://github.com/permissionlesstech/bitchat/blob/main/BLELinkStateStore.swift) stores link-layer state including queues and buffers, strictly confined to the `bleQueue`. This isolation ensures that CoreBluetooth callbacks never contend with protocol logic for shared mutable state.

### BLELinkAuthState.swift

[`BLELinkAuthState.swift`](https://github.com/permissionlesstech/bitchat/blob/main/BLELinkAuthState.swift) tracks authentication state for each link. In the V3 redesign, this state moved from the `bleQueue` to the engine to support atomic rebind checks during peer verification.

### BLELinkBindings.swift

[`BLELinkBindings.swift`](https://github.com/permissionlesstech/bitchat/blob/main/BLELinkBindings.swift) maintains the mapping between physical links and logical peers. Like authentication state, these bindings are now owned by the serial engine rather than the link layer, enabling consistent state transitions during connection migration.

### BLELinkEvent.swift and BLEEngineScheduler.swift

[`BLELinkEvent.swift`](https://github.com/permissionlesstech/bitchat/blob/main/BLELinkEvent.swift) defines the `LinkEvent` enum used for upward communication from the link layer to the engine, while [`BLEEngineScheduler.swift`](https://github.com/permissionlesstech/bitchat/blob/main/BLEEngineScheduler.swift) runs the serial engine queue and coordinates `onEngine` calls. The scheduler enforces the architecture's concurrency contract by ensuring all engine-confined state mutations occur on the serial queue.

## Concurrency Contracts and Queue Architecture

The V3 architecture enforces a strict **concurrency contract** across all BLE components. Engine-confined state is mutated only on the serial engine queue, while `bleQueue`-confined state lives alongside CoreBluetooth objects. Lock-backed stores—such as the peer registry—provide safe cross-domain reads without blocking either queue. This design eliminates deadlocks, simplifies unit testing, and enables deterministic simulation of mesh behaviors.

## Practical Implementation Examples

The following Swift snippets illustrate how V3 components interact in practice:

```swift
// Emit a link-layer event from BLELinkLayer when a packet arrives
let packet = Data(...)
let linkID = UUID()
BLEEngineScheduler.shared.emitLinkEvent(.frameDecoded(linkID: linkID, packet: packet))

```

```swift
// Engine-side handler processing events and routing through the mesh
BLEEngineScheduler.shared.onEngine { engine in
    switch engine.handleLinkEvent(event) {
    case .forward(let effect):
        engine.apply(effect)  // Update peer registry, schedule ack, etc.
    case .drop(let reason):
        break
    }
}

```

```swift
// Access a lock-backed peer store from the main actor (read-only)
let isConnected = BLEPeerRegistryStore.shared.isPeerConnected(peerID)

```

```swift
// Query link authentication state (engine-owned) for a specific link
let authState = BLELinkAuthState.shared.state(for: linkID)

```

## Summary

- **BLELinkLayer** manages all CoreBluetooth interactions, scanning, advertising, and connection state on the dedicated `bleQueue`.
- **Mesh Engine** processes all protocol logic—including packet fragmentation, deduplication, and peer registry updates—on a serial engine queue.
- **Feature Modules** register for specific message types while maintaining isolated state, preventing feature creep in the core engine.
- **App Boundary** exposes a clean `Transport` protocol to the application layer, delegating implementation details to the engine.
- **Strict concurrency contracts** segregate state between the `bleQueue`, serial engine queue, and lock-backed stores to prevent deadlocks.

## Frequently Asked Questions

### What is the role of BLELinkLayer in the V3 architecture?

**BLELinkLayer** is the low-level component that directly interfaces with CoreBluetooth. It manages scanning, advertising, connection establishment, MTU negotiation, and back-pressure buffers. It communicates upward to the Mesh Engine via `LinkEvent` enums and receives commands via `LinkCommand`, keeping all radio-specific logic isolated from protocol processing.

### How does the Mesh Engine handle concurrent state access?

The Mesh Engine runs on a **single-writer serial queue** coordinated by [`BLEEngineScheduler.swift`](https://github.com/permissionlesstech/bitchat/blob/main/BLEEngineScheduler.swift). All state mutations—including peer registry updates and packet processing—occur exclusively on this queue. Lock-backed stores provide thread-safe read access from other queues, ensuring the engine never blocks waiting for external locks while maintaining consistency.

### What does BLELinkBindings.swift manage?

[`BLELinkBindings.swift`](https://github.com/permissionlesstech/bitchat/blob/main/BLELinkBindings.swift) maintains the mapping between physical BLE links (identified by hardware addresses or CoreBluetooth identifiers) and logical peers in the mesh network. In V3, this state moved from the link layer to the engine, enabling atomic updates when connections migrate or rebinding occurs during authentication handshakes.

### How do Feature Modules communicate with the BLE stack?

Feature Modules register with the Mesh Engine to receive specific message types while maintaining their own isolated state. They do not interact directly with **BLELinkLayer** or the `bleQueue`. Instead, they send and receive data through the engine's serial queue, ensuring that feature-specific logic never interferes with low-level radio timing or connection state management.