peat-btle 0.3.0

Bluetooth Low Energy mesh transport for Peat Protocol
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
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
# HIVE / peat-btle Architecture Refactoring Plan

**Status**: **Decisions Made** - Ready for Implementation
**Date**: 2026-01-25 (updated)
**Authors**: Kit, Codex
**Stakeholders**: HIVE Team, ATAK Plugin Team, WearTAK Team

> **Summary of Key Decisions** (2026-01-25):
> 1. **hive-lite** → Separate repo (leaf crate, no HIVE deps, `no_std`)
> 2. **CannedMessage** → Predefined message codes replace ChatCRDT
> 3. **Emergency** → Becomes `CannedMessage::Emergency`
> 4. **peat-btle** → Transport only; `standalone` feature adds hive-lite dep
> 5. **Translation layer** → Lives in hive-protocol, not transports

---

## Executive Summary

The current peat-btle library conflates two different responsibilities:
1. **BLE Transport** - Moving bytes over Bluetooth Low Energy
2. **Document/CRDT Logic** - Defining and merging application data structures

This has caused bugs (chat not syncing) and architectural confusion. This document proposes a clear separation of concerns between HIVE (protocol layer) and peat-btle (transport layer).

---

## Table of Contents

1. [Problem Statement]#problem-statement
2. [Current Architecture (Problematic)]#current-architecture-problematic
3. [Root Cause Analysis]#root-cause-analysis
4. [Proposed Architecture]#proposed-architecture
5. [Migration Tasks]#migration-tasks
6. [Open Questions]#open-questions
7. [Decision Log]#decision-log

---

## Problem Statement

### Symptoms

1. **Chat messages don't sync reliably** between WearTAK devices and ATAK plugin
2. **Duplicate delta sync implementations** - Kotlin builds delta operations separately from Rust
3. **Architectural confusion** - Unclear what peat-btle should know about vs HIVE

### The Specific Bug

From device testing:
```
[ENCRYPTED-MERGE] sourceNode=B1063BF6, isAck=false, counterChanged=false, total=0
```

- Watch 2 has `chatCount=1` locally
- Plugin receives `total=0` - chat state missing
- Location/callsign sync works, but chat doesn't propagate

### Root Cause

In `PeatBtle.kt`, the `buildSyncDocumentForPeer()` function has two paths:

1. **Full sync** (every 10th sync): Uses native `buildDocument()` which includes chat ✓
2. **Delta sync** (9/10 syncs): Builds Kotlin-side delta operations ✗

The Kotlin delta operations only include:
- `IncrementCounter`
- `UpdateLocation`
- `UpdateHealth`
- `UpdateCallsign`
- `UpdateEvent`

**Chat is NOT included in delta operations** - so 90% of syncs don't send chat.

---

## Current Architecture (Problematic)

```
┌─────────────────────────────────────────────────────────────────┐
│                        peat-btle                                 │
│  (Currently owns too much)                                       │
├─────────────────────────────────────────────────────────────────┤
│  ✓ Platform adapters (BlueZ, CoreBluetooth, Android, ESP32)     │
│  ✓ GATT service & fragmentation                                 │
│  ✓ Mesh relay                                                   │
│  ✓ Encryption primitives                                        │
│  ✓ Discovery & connection management                            │
├─────────────────────────────────────────────────────────────────┤
│  ✗ PeatDocument format (counter, peripheral, emergency, chat)   │
│  ✗ CRDT implementations (GCounter, ChatCRDT, EmergencyEvent)    │
│  ✗ Delta sync with CRDT-specific operations                     │
│  ✗ Document merge semantics                                     │
│  ✗ Identity/Genesis/Security policy                             │
│  ✗ Hierarchy levels                                             │
└─────────────────────────────────────────────────────────────────┘
```

### What peat-btle Currently Defines

| Component | Location | Problem |
|-----------|----------|---------|
| `PeatDocument` | `src/document.rs` | Application-level structure in transport |
| `ChatCRDT` | `src/sync/crdt.rs` | Chat is a HIVE concept, not transport |
| `GCounter` | `src/sync/crdt.rs` | Counter semantics belong in HIVE |
| `EmergencyEvent` | `src/sync/crdt.rs` | Emergency protocol is HIVE-level |
| `DeltaDocument` | `src/sync/delta_document.rs` | CRDT-specific operations |
| `MeshGenesis` | `src/security/genesis.rs` | Trust policy is HIVE-level |
| `HierarchyLevel` | `src/peat_mesh.rs` | Hierarchy is HIVE concept |

---

## Root Cause Analysis

### Two Different Use Cases Conflated

**Use Case 1: Standalone Embedded Mesh** (ESP32 sensors without HIVE)
- Needs lightweight CRDTs in peat-btle
- Self-contained document format
- Valid for ESP32-to-ESP32 mesh

**Use Case 2: HIVE Transport Layer** (WearTAK, phones with full HIVE)
- Should be opaque byte transport
- HIVE manages documents via Automerge/Ditto
- peat-btle should just move bytes

**The problem**: These are not clearly separated. The Android/Kotlin code tries to use both, causing bugs.

### HIVE Ontology Review

The HIVE project has 8 core protobuf schemas:

| Schema | Purpose |
|--------|---------|
| `cap.common.v1` | Uuid, Timestamp, Position |
| `cap.node.v1` | Platform definitions |
| `cap.capability.v1` | Capability discovery |
| `cap.cell.v1` | Squad formation |
| `cap.zone.v1` | Hierarchy coordination |
| `cap.role.v1` | Role assignments |
| `cap.beacon.v1` | Discovery phase |
| `cap.composition.v1` | Capability composition |

**Key Finding**: No "chat" or "messaging" in the core HIVE ontology.

### Where Should Chat Live?

| Layer | Responsibility | Chat? |
|-------|----------------|-------|
| hive-schema | Domain models (protobuf) | Add `cap.message.v1` if needed |
| hive-protocol | Sync abstraction | Document type definition |
| hive-persistence | Automerge/Ditto backends | CRDT storage & merge |
| hive-lite | Constrained primitives | **NO** - too complex for 256KB |
| peat-btle | BLE transport | **NO** - just moves bytes |

---

## Proposed Architecture

```
┌─────────────────────────────────────────────────────────────────┐
│                        HIVE (Protocol Layer)                     │
├─────────────────────────────────────────────────────────────────┤
│  hive-schema     │ Protobuf definitions (node, cell, message?)  │
│  hive-protocol   │ DataStore, SyncCapable traits                │
│  hive-persistence│ Automerge/Ditto document storage             │
│  hive-lite       │ Constrained primitives (LWW, counters only)  │
└─────────────────────────────────────────────────────────────────┘
                    ┌─────────┴─────────┐
                    │  Translation API   │
                    │  (thin, in HIVE)   │
                    └─────────┬─────────┘
┌─────────────────────────────────────────────────────────────────┐
│                   peat-btle (Transport Layer)                    │
├─────────────────────────────────────────────────────────────────┤
│  Platform adapters (BlueZ, CoreBluetooth, Android, ESP32)       │
│  GATT service & fragmentation                                   │
│  Mesh relay (forward opaque bytes)                              │
│  Encryption primitives (encrypt/decrypt with provided key)      │
│  Discovery & connection management                              │
│                                                                 │
│  [STANDALONE MODE - feature-gated]:                             
│  Lightweight CRDTs for ESP32-only mesh (no HIVE integration)    │
└─────────────────────────────────────────────────────────────────┘
```

### Target peat-btle API

**Current API** (wrong - knows about documents):
```rust
pub fn build_document(&self) -> Vec<u8>;
pub fn merge_document(&self, data: &[u8]) -> MergeResult;
pub fn send_chat(&self, sender: &str, text: &str);
pub fn send_emergency(&self, known_peers: &[u32]);
```

**Target API** (correct - opaque transport):
```rust
pub trait BleTransport {
    /// Send data to a specific peer
    fn send(&self, peer: NodeId, data: &[u8]) -> Result<()>;

    /// Broadcast data to all connected peers
    fn broadcast(&self, data: &[u8]) -> Result<()>;

    /// Set callback for received data
    fn on_receive(&self, callback: fn(NodeId, &[u8]));

    /// Encryption (key provided by HIVE layer)
    fn set_encryption_key(&self, key: &[u8; 32]);
    fn encrypt(&self, plaintext: &[u8]) -> Vec<u8>;
    fn decrypt(&self, ciphertext: &[u8]) -> Result<Vec<u8>>;
}
```

**Feature-gated standalone mode** (for ESP32 without HIVE):
```rust
#[cfg(feature = "standalone")]
pub mod standalone {
    // Lightweight CRDTs for ESP32-only mesh
    // NOT for use with full HIVE integration
    pub struct StandaloneDocument { ... }
    pub fn build_standalone_document(&self) -> Vec<u8>;
    pub fn merge_standalone_document(&self, data: &[u8]);
}
```

---

## Migration Tasks

### Phase 1: HIVE Team - Define Messaging (if needed)

#### Task 1.1: Decide on Tactical Messaging Scope

**Question**: Is tactical text messaging in scope for HIVE protocol?

Options:
- **A**: Yes - Add `cap.message.v1` to hive-schema
- **B**: No - Messaging handled externally (TAK, etc.)
- **C**: Defer - Focus on core protocol first

**Assigned to**: _____________
**Decision date**: _____________

#### Task 1.2: Add Message Schema (if Option A)

**File**: `hive-schema/proto/cap/message/v1/message.proto`

```protobuf
syntax = "proto3";
package cap.message.v1;

import "cap/common/v1/common.proto";

// Tactical text message (HIVE-Full only, not for hive-lite)
message TextMessage {
  cap.common.v1.Uuid id = 1;
  cap.common.v1.Uuid sender_id = 2;
  cap.common.v1.Timestamp timestamp = 3;
  string sender_callsign = 4;
  string text = 5;
  optional cap.common.v1.Uuid reply_to = 6;
  bool broadcast = 7;
}

message MessageCollection {
  repeated TextMessage messages = 1;
  // CRDT semantics: Append-only or RGA for ordering
}
```

**Assigned to**: _____________
**Target date**: _____________

#### Task 1.3: Implement Message Sync in hive-persistence

- Store messages in Automerge document
- Use appropriate CRDT (append-only log or RGA)
- Implement `DataStore` trait for messages
- Handle merge conflicts

**Assigned to**: _____________
**Target date**: _____________

---

### Phase 2: Translation Layer

#### Task 2.1: Define Translation API

**Location**: `hive-protocol/src/transport/ble_bridge.rs` (or new crate)

```rust
/// Bridge between HIVE documents and peat-btle transport
pub trait BleBridge {
    /// Serialize current HIVE state for BLE transmission
    fn serialize_for_ble(&self) -> Vec<u8>;

    /// Deserialize received BLE data into HIVE updates
    fn apply_from_ble(&self, data: &[u8]) -> Result<()>;

    /// Get encryption key for mesh
    fn mesh_encryption_key(&self) -> &[u8; 32];
}
```

**Key decisions**:
- [ ] Where does this live? (hive-protocol, new crate, or apps)
- [ ] What serialization format? (Protobuf, custom binary, JSON)
- [ ] How to handle version compatibility?

**Assigned to**: _____________
**Target date**: _____________

---

### Phase 3: peat-btle Refactoring

#### Task 3.1: Feature-Gate Standalone Mode

Add feature flag to separate standalone embedded use from HIVE integration:

```toml
# Cargo.toml
[features]
default = ["transport"]
transport = []  # Pure transport layer
standalone = ["transport"]  # Includes lightweight CRDTs for ESP32-only mesh
```

**Assigned to**: _____________
**Target date**: _____________

#### Task 3.2: Refactor Public API

Move document-aware methods behind `standalone` feature:

```rust
// Always available (transport layer)
impl PeatMesh {
    pub fn send(&self, peer: NodeId, data: &[u8]) -> Result<()>;
    pub fn broadcast(&self, data: &[u8]) -> Result<()>;
    pub fn on_data_received(&self, peer: NodeId, data: &[u8]);
}

// Only with standalone feature
#[cfg(feature = "standalone")]
impl PeatMesh {
    pub fn build_document(&self) -> Vec<u8>;
    pub fn merge_document(&self, data: &[u8]) -> MergeResult;
    pub fn send_chat(&self, sender: &str, text: &str) -> Option<Vec<u8>>;
}
```

**Assigned to**: _____________
**Target date**: _____________

#### Task 3.3: Update Android/Kotlin Integration

Remove Kotlin-side delta building. HIVE layer provides bytes, Kotlin just transports.

**Current** (wrong):
```kotlin
private fun buildSyncDocumentForPeer(...): ByteArray? {
    val operations = mutableListOf<DeltaOperation>()
    // Kotlin manually builds deltas - chat missing!
}
```

**Target** (correct):
```kotlin
// HIVE layer provides serialized state
val documentBytes = hiveProtocol.serializeForBle()

// peat-btle just transports
hiveBtle.broadcast(documentBytes)
```

**Assigned to**: _____________
**Target date**: _____________

---

### Phase 4: Documentation & Testing

#### Task 4.1: Update Architecture Documentation

- [ ] Update peat-btle README to clarify scope
- [ ] Add ADR for transport/protocol separation
- [ ] Document standalone vs HIVE integration modes
- [ ] Update Codex.md with new architecture

#### Task 4.2: Integration Tests

- [ ] Test HIVE → peat-btle → HIVE round-trip
- [ ] Test message sync across mesh
- [ ] Test standalone ESP32 mesh (no HIVE)
- [ ] Performance benchmarks

---

## Open Questions

### Q1: Is tactical messaging in scope for HIVE?

**Context**: The current peat-btle ChatCRDT was added for WearTAK use. HIVE core ontology doesn't include messaging.

**Options**:
- A: Add `cap.message.v1` to HIVE schema
- B: Keep messaging external (TAK integration)
- C: Messaging is app-level concern, not protocol

**Decision**: **D: CannedMessage primitive in hive-lite** (2026-01-25)
**Rationale**: WearTAK needs ACK/Emergency, not full chat. Predefined message codes fit 256KB budget. Full text messaging (if needed) would be HIVE-Full only via `cap.message.v1`.

---

### Q2: Where should the translation layer live?

**Options**:
- A: In `hive-protocol` crate
- B: New `peat-btle-bridge` crate
- C: In each app (Android, iOS, etc.)

**Decision**: _____________
**Rationale**: _____________

---

### Q3: What happens to existing peat-btle users?

**Concern**: Breaking changes for standalone ESP32 users.

**Options**:
- A: Major version bump (0.x → 1.0) with migration guide
- B: Feature flags to maintain backward compatibility
- C: Deprecation period with warnings

**Decision**: _____________
**Rationale**: _____________

---

### Q4: Should standalone mode support chat?

**Current**: peat-btle has ChatCRDT in standalone mode

**Concern**: Chat is complex for 256KB RAM budget (hive-lite target)

**Options**:
- A: Remove ChatCRDT from standalone (simplify)
- B: Keep but document limitations
- C: Make chat optional within standalone

**Decision**: **A: Remove ChatCRDT, replace with CannedMessage** (2026-01-25)
**Rationale**: CannedMessage covers WearTAK's ACK/Emergency needs. Full ChatCRDT will be deprecated. hive-lite provides bounded, predictable memory usage.

---

### Q5: Timeline for Automerge backend?

**Context**: hive-persistence Phase 7 (Automerge+Iroh) is in progress.

**Questions**:
- When will it support custom document types (messages)?
- Can we test message sync before full completion?

**Status**: _____________

---

## Decision Log

| Date | Decision | Rationale | Participants |
|------|----------|-----------|--------------|
| 2026-01-25 | Document created | Initial analysis of chat sync bug | Kit, Codex |
| 2026-01-25 | **hive-lite as separate repo** | Leaf crate with no HIVE deps; reusable by peat-btle, hive-lora, future transports | Kit, Codex |
| 2026-01-25 | **CannedMessage primitive** | Predefined message codes (ACK, EMERGENCY, etc.) fit 256KB budget; no free-text chat in hive-lite | Kit, Codex |
| 2026-01-25 | **Emergency → CannedMessage** | Unify event types; Emergency becomes `CannedMessage::Emergency` | Kit, Codex |
| 2026-01-25 | **ChatCRDT deprecated** | Full chat doesn't fit hive-lite; will be removed or feature-gated in peat-btle | Kit, Codex |

---

## References

- [HIVE ADR-010: Transport Abstraction]../hive/docs/adr/010-transport-abstraction.md
- [HIVE ADR-011: Automerge+Iroh Backend]../hive/docs/adr/011-automerge-iroh.md
- [HIVE ADR-032: Transport Trait]../hive/docs/adr/032-transport-trait.md
- [HIVE ADR-035: HIVE-Lite Embedded Nodes]../hive/docs/adr/035-hive-lite.md
- [HIVE ADR-037: Differential Sync]../hive/docs/adr/037-differential-sync.md
- [HIVE ADR-039: PEAT-BTLE Mesh Transport]../hive/docs/adr/039-peat-btle.md
- [peat-btle Issue cc953d6: Delta Sync Integration]https://app.radicle.xyz/nodes/seed.radicle.garden/rad:z458mp9Um3AYNQQFMdHaNEUtmiohq/issues/cc953d6

---

## Appendix A: Current peat-btle Document Format

For reference, the current `PeatDocument` structure that would be deprecated for HIVE integration:

```rust
pub struct PeatDocument {
    pub version: u32,
    pub node_id: NodeId,
    pub counter: GCounter,
    pub peripheral: Option<Peripheral>,
    pub emergency: Option<EmergencyEvent>,
    pub chat: Option<ChatCRDT>,
}
```

Wire format markers:
- `0xAA` - Unencrypted PeatDocument
- `0xAE` - Encrypted PeatDocument
- `0xAC` - Emergency section
- `0xAD` - Chat section
- `0xB2` - Delta document

---

## Appendix B: hive-lite Memory Budget

From ADR-035, the 256KB target allocation:

| Component | Budget | Notes |
|-----------|--------|-------|
| Network stack | 64KB | lwIP/smoltcp |
| CRDT state | 64KB | ~100 LWW registers |
| Gossip buffers | 32KB | 64 × 512-byte packets |
| Protocol state | 16KB | Peer table, routing |
| Application | 80KB | Sensor logic, display |

**Implication**: Full chat history doesn't fit in hive-lite budget.

---

## Appendix C: hive-lite Crate Architecture

### Decision: Separate Repository

hive-lite will be a **separate repository** (`hive-lite`), not a workspace member of peat-btle or hive. This enables:

1. **Reuse by multiple transports**: peat-btle, hive-lora (future), ESP-NOW
2. **Independent versioning**: Primitives may stabilize faster than transport implementations
3. **Clean dependency tree**: No circular dependencies with HIVE ecosystem

### Dependency Graph

```
                    ┌─────────────┐
                    │  hive-ffi   │
                    └──────┬──────┘
                    ┌──────▼──────┐
                    │hive-protocol│
                    └──────┬──────┘
              ┌────────────┼────────────┐
              │            │            │
              ▼            ▼            ▼
        ┌──────────┐ ┌──────────┐ ┌──────────┐
        │hive-schema│ │peat-btle │ │hive-lora │
        └──────────┘ │(transport)│ │ (future) │
                     └─────┬─────┘ └────┬─────┘
                           │            │
                           │ optional   │ optional
                           │ dep        │ dep
                           ▼            ▼
                     ┌─────────────────────┐
                     │      hive-lite      │  ← LEAF (no upward deps)
                     │   (primitives)      │
                     └─────────────────────┘
```

**Key constraint**: hive-lite has **zero dependencies** on hive-schema, hive-protocol, or any HIVE crate. It is a leaf node in the dependency tree.

### hive-lite Contents

```rust
// hive-lite/src/lib.rs
#![no_std]  // no_std by default

pub mod node_id;       // NodeId (u32)
pub mod canned;        // CannedMessage enum and store
pub mod lww;           // LwwRegister<T>
pub mod counter;       // GCounter, PnCounter
pub mod wire;          // Binary encoding/decoding
pub mod event;         // LiteEvent (bounded event store)
```

### CannedMessage Definition

```rust
/// Predefined message codes for resource-constrained devices
/// Designed for button-based interaction (no keyboard input)
#[repr(u8)]
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum CannedMessage {
    // Acknowledgments (0x00-0x0F)
    Ack = 0x00,           // "Message received"
    AckWilco = 0x01,      // "Will comply"
    AckNegative = 0x02,   // "Cannot comply"

    // Status (0x10-0x1F)
    CheckIn = 0x10,       // "I'm here / still alive"
    Moving = 0x11,        // "En route"
    Holding = 0x12,       // "Stationary / waiting"
    OnStation = 0x13,     // "Arrived at position"

    // Alerts (0x20-0x2F)
    Emergency = 0x20,     // "Need immediate help" (replaces EmergencyEvent)
    Alert = 0x21,         // "Attention needed"
    AllClear = 0x22,      // "Situation resolved"

    // Requests (0x30-0x3F)
    NeedExtract = 0x30,   // "Request pickup"
    NeedSupport = 0x31,   // "Request assistance"
    NeedMedic = 0x32,     // "Medical emergency"

    // Reserved (0xF0-0xFF)
    Custom = 0xFF,        // For future/app-specific use
}

/// Bounded event store - LWW per (source_node, message_type)
/// Memory usage: max_peers × 8 event_types × 24 bytes ≈ 9.6KB for 50 peers
pub struct CannedMessageStore {
    messages: heapless::FnvIndexMap<(NodeId, CannedMessage), CannedMessageEvent, 400>,
}

pub struct CannedMessageEvent {
    pub message: CannedMessage,   // 1 byte
    pub source_node: NodeId,      // 4 bytes
    pub target_node: Option<NodeId>, // 5 bytes (1 + 4)
    pub timestamp: u64,           // 8 bytes
    pub sequence: u32,            // 4 bytes
}                                 // Total: ~24 bytes
```

### Wire Format

New marker byte `0xAF` for CannedMessage:

```
┌──────┬──────────┬──────────┬──────────┬───────────┬──────┐
│ 0xAF │ msg_code │ src_node │ tgt_node │ timestamp │ seq  │
│ 1B   │ 1B       │ 4B       │ 4B (opt) │ 8B        │ 4B   │
└──────┴──────────┴──────────┴──────────┴───────────┴──────┘
```

- Minimum: 14 bytes (no target)
- Maximum: 18 bytes (with target)

### peat-btle Integration

```toml
# peat-btle/Cargo.toml
[features]
default = ["std", "standalone"]
standalone = ["dep:hive-lite"]  # Include primitives
transport-only = []              # Pure byte transport

[dependencies]
hive-lite = { version = "0.1", optional = true }
```

### Translation Layer

hive-protocol (or apps) translates between hive-lite and HIVE-Full:

| hive-lite | HIVE-Full (Automerge) |
|-----------|----------------------|
| `CannedMessage::Ack` | Event in document: `{ type: "ack", from: ..., ts: ... }` |
| `CannedMessage::Emergency` | Alert document with severity=critical |
| `LwwRegister<Position>` | `cap.common.v1.Position` in Automerge doc |
| `GCounter` | Automerge counter |

The translation layer lives in **hive-protocol**, not hive-lite or peat-btle.

---

## Appendix D: Implementation Roadmap

### Phase 0: Create hive-lite (Immediate)

**Owner**: Core Team
**Target**: This week

- [ ] Create `hive-lite` repository
- [ ] Implement `NodeId` (u32 wrapper)
- [ ] Implement `CannedMessage` enum
- [ ] Implement `CannedMessageStore` (bounded LWW store)
- [ ] Implement `LwwRegister<T>`
- [ ] Implement `GCounter`
- [ ] Wire format encoding/decoding
- [ ] `no_std` compatible, optional `std` feature
- [ ] Basic tests

### Phase 1: Integrate hive-lite into peat-btle

**Owner**: peat-btle Team
**Target**: Following week
**Depends on**: Phase 0

- [ ] Add `hive-lite` as optional dependency
- [ ] Add `standalone` feature flag
- [ ] Migrate `GCounter` to use hive-lite's
- [ ] Replace `EmergencyEvent` with `CannedMessage::Emergency`
- [ ] Replace ACK handling with `CannedMessage::Ack`
- [ ] Deprecate `ChatCRDT` (feature-gate or remove)
- [ ] Update Android/Kotlin bindings for CannedMessage
- [ ] Wire format: add `0xAF` marker for CannedMessage

### Phase 2: Update ATAK Plugin

**Owner**: ATAK Plugin Team
**Target**: Following Phase 1
**Depends on**: Phase 1

- [ ] Update peat-btle dependency
- [ ] Replace chat-based ACK with CannedMessage ACK
- [ ] Update UI to show CannedMessage events
- [ ] Test with WearTAK devices

### Phase 3: Translation Layer (Future)

**Owner**: HIVE Protocol Team
**Target**: TBD
**Depends on**: Phase 1

- [ ] Define translation API in hive-protocol
- [ ] Map CannedMessage ↔ Automerge events
- [ ] Map LwwRegister ↔ Automerge fields
- [ ] Integration tests

### Phase 4: hive-lora Integration (Future)

**Owner**: TBD
**Target**: TBD
**Depends on**: Phase 0

- [ ] Create hive-lora transport crate
- [ ] Add hive-lite dependency
- [ ] Implement LoRa-specific wire format optimizations