Expand description
Universal Document envelope for cross-transport sync.
Carries an opaque document body (collection name + id + timestamp + body bytes) so adding a new collection to the network requires zero changes to peat-lite, peat-btle, or future LoRa transports — only the publisher and the consumer agree on the body shape. This formalizes the universal half of ADR-059 Amendment 4’s universal-vs-application-domain split: typed sensor primitives (peripheral health, BLE position, canned messages) keep their domain-specific carriers in peat-btle / peat-protocol; arbitrary Documents (markers, platforms, tracks, future collections) flow through this envelope.
§Wire layout
Carried as the payload of a [MessageType::Document] frame
(header byte 0x07). The header (16 bytes, super::header) is
followed immediately by:
┌──────────────┬────────────────┬───────────────┬────────────┬──────────────┬──────┐
│ flags │ collection_len │ collection │ doc_id_len│ doc_id │ ... │
│ 1 byte │ 1 byte │ N bytes │ 2 bytes LE│ M bytes │ │
├──────────────┼────────────────┼───────────────┴────────────┴──────────────┘ │
│ timestamp_ms │ body_len │ body │
│ 8 bytes LE │ 2 bytes LE │ K bytes (opaque) │
└──────────────┴────────────────┴──────────────────────────────────────────────────┘flags: bit 0 = deletion-tombstone (body MAY be empty); bit 1 = encrypted body; bits 2–7 reserved (must encode 0).collection: UTF-8, length-prefixed by 1 byte (0–255). Empty collection name is invalid and rejected on decode.doc_id: UTF-8, length-prefixed by 2-byte LE length (0–65535).doc_id_len = 0means the publisher delegates id assignment to the receiving doc store (matchingpeat_mesh::Node::publish’s contract for Documents withid: None).timestamp_ms: Unix epoch milliseconds, 8-byte LE i64. Used by the receiving CRDT layer for last-writer-wins resolution where applicable; lower layers don’t interpret it.body: opaque bytes, length-prefixed by 2-byte LE length (0–65535). peat-lite does not interpret the body; consumers (peat-mesh, peat-atak-plugin, M5Stack firmware) own the body schema. Postcard-encodedpeat_mesh::Document.fieldsis the conventional choice on the host side, but the wire is agnostic.
§Size limits and fragmentation
Field maxima:
collection: 255 bytes — comfortably above all current collection names (markers,platforms,tracks,company_summaries,canned_messages, …).doc_id: 65535 bytes — UUIDs (36) and CoT UIDs (~64) fit easily.body: 65535 bytes — well above peat-lite’s [MAX_PAYLOAD_SIZE] (496 bytes). For LoRa-class transports carrying envelopes that fit in a single packet, the spec is bounded by the transport, not the codec.
Total framed envelope on the wire:
header(16) + 1 + 1 + N + 2 + M + 8 + 2 + K = 30 + N + M + K
When the framed envelope exceeds MAX_PAYLOAD_SIZE, the
transport is responsible for fragmenting (peat-btle’s
chunk_data / ChunkReassembler over GATT, LoRa’s scheduler,
etc.). peat-lite envelopes stay opaque to the chunking layer; this
keeps the codec transport-agnostic and lets each radio choose the
fragmentation strategy that fits its MTU + duty-cycle constraints.
Structs§
- Document
Ref - Decoded view of a Document envelope, borrowing from the input
buffer. Hot-path-friendly for
no_stdconsumers — no allocation.
Constants§
- DOC_
FLAGS_ MASK - Mask of currently-defined flag bits. Bits set outside this mask
are reserved for future protocol versions; today’s encoder
rejects them with
MessageError::InvalidFlagsso that legacy frames can’t enable not-yet-implemented behaviors. Round-2 of peat-lite#26 added this reservation contract. - DOC_
FLAG_ ENCRYPTED - Bit 1: body is encrypted (per-document, key established
out-of-band). Reserved for a future encryption layer; today’s
encoder rejects the flag entirely (returns
MessageError::InvalidFlags) so a conforming sender will never ship a frame with this bit set. - DOC_
FLAG_ TOMBSTONE - Bit 0: deletion tombstone — the publisher is deleting the document
referenced by
(collection, doc_id). Body MUST be empty; the encoder rejectstombstone | body.len() > 0to prevent publisher-side write-then-delete contract violations. - MAX_
BODY_ LEN - Maximum body byte length on the wire (2-byte length prefix
limit). Transport-level fragmentation may carry envelopes larger
than peat-lite’s [
MAX_PAYLOAD_SIZE], up to this hard cap. - MAX_
COLLECTION_ LEN - Maximum length of a collection name on the wire (1-byte length prefix limit).
- MAX_
DOC_ ID_ LEN - Maximum length of a doc id on the wire (2-byte length prefix limit).
Functions§
- decode
- Decode a Document envelope from
buf(the payload region after the 16-byte peat-lite header). Returns a borrowing view; bumps any length-related parse error to a single error variant rather than returning partial data, matching how the rest of the protocol module surfaces malformed wire input. - encode
- Encode a Document envelope into
buf. Returns the number of bytes written, or an error if any field exceeds its width, the buffer is too small, or the flags / tombstone-vs-body invariants are violated. - encoded_
len - Encoded length of a Document envelope with the given field sizes,
excluding the 16-byte peat-lite header. Useful for callers
preflight-checking a buffer against [
MAX_PAYLOAD_SIZE] before committing to a single-packet send vs. fragmentation.