Skip to main content

Module document

Module document 

Source
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 = 0 means the publisher delegates id assignment to the receiving doc store (matching peat_mesh::Node::publish’s contract for Documents with id: 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-encoded peat_mesh::Document.fields is 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§

DocumentRef
Decoded view of a Document envelope, borrowing from the input buffer. Hot-path-friendly for no_std consumers — 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::InvalidFlags so 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 rejects tombstone | body.len() > 0 to 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.