Tighten the encryption steps to spell out:
- Plaintext is zero-padded on the right to a multiple of 16 bytes
before AES-128-ECB encryption.
- The padding is NOT PKCS#7 (not unambiguous); the receiver must
disambiguate trailing zeros using the inner plaintext format
(e.g., for TXT_MSG, by C-string NUL termination scan).
- Renumber steps so the padding step is explicit and ordered before
encryption, instead of being a parenthetical on the encrypt step.
Validated against upstream meshcore-dev/MeshCore @ 1a7b361
(Utils::encrypt / Utils::decrypt, src/Utils.cpp:30-, comment
"dest may contain trailing zero bytes in final block").
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Two additions to the TXT_MSG section:
1. Attempt Counter Semantics. Spells out that bits 0-1 of
txt_type_attempt carry attempt & 3, the input the ACK CRC depends
on. For attempt > 3, upstream appends a [NUL][attempt_full] tail
after the text (BaseChatMesh.cpp:410-412), recovering the full
attempt value at the cost of 2 bytes of text capacity. The tail is
NOT part of the ACK CRC input, so attempt=4 and attempt=0 collide
on CRC and senders relying on >3 must verify the trailing byte.
2. Reliable DM Delivery. Documents the sender-side ACK tracking
contract: maintain a pending-ACK table keyed by expected CRC,
retry with attempt incremented, consume MULTIPART-wrapped or plain
ACKs identically, and the receive-side option to cache replies per
peer for duplicate-DM loss recovery.
Validated against upstream meshcore-dev/MeshCore @ 1a7b361
(BaseChatMesh::composeMsgPacket, onPeerDataRecv TXT_MSG handling).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>