v0.12.0
[0.12.0] - 2026-07-13
Features
- Carry an is_admin hint in relay group registration (protocol) (87067e3)
- Relay-native translation for control ops and generic server channel (bindings) (2d5db61)
- Tag server-plane control frames for bridge translation (protocol+uniffi) (a2cd686)
- TS surface for relay presence (bindings) (3577301)
- Relay DeliveryError fail-fast, presence ingestion, and watch loop (bindings) (110bf9b)
- Expose internet_peer_presence and presence watchlist (uniffi) (e015554)
- Ingest per-peer presence to park and rescue welcomes (protocol) (b0eb215)
- Bridge relay TypingUpdate into the typing event path (bindings) (d2679d5)
- Surface new error taxonomy to mobile callers (bindings) (0236778)
- Coherent error taxonomy across the FFI boundary (uniffi) (9838d75)
- Typed error variants for group-mesh failures (protocol) (d773c01)
- Expose validate_id_chars for cross-crate id validation (core) (89daf38)
Bug Fixes
- Bound pending-decryption-queue memory against forged senders (protocol) (a21f11b)
- Clamp key-package lifetime and prune restore overflow (protocol) (1c7c47a)
- Authorize group-member-added off the relay path; cap pending key packages (protocol) (9c14301)
- Authenticate group message + membership handlers off the sender (protocol) (af4859a)
- Authorize group removal off the sender, not removed_by (protocol) (4958146)
- Bind a Welcome's embedded group id to the wire slot (mls) (19d8cbb)
- Extend SEC-M6 slot binding to the group-Welcome path (mls) (9c32558)
- Bind Welcome session slot to the authenticated inviter (SEC-M6) (mls) (e1b290a)
- IOS pause-drain re-arm actually fires after reconnect (bindings) (5afcbd8)
- IOS pause drain re-arms once control chains settle (bindings) (fc969bb)
- Don't silently drop undeserializable outbox frames (uniffi) (b3fdbc3)
- Reject unsigned control frames in strict identity mode (protocol) (8ff2ea0)
- Hop the iOS pause drain onto messageQueue (bindings) (b9233c8)
- Drain-once pause semantics; wire iOS internet pause; drop Android no-op ping (bindings) (2b5fd1d)
- Synthesized relay frames failed Rust deserialization and were silently dropped (bindings) (4259b21)
- Hop-aware transport-identity gate + wire internet sender attribution (protocol) (d65f62c)
- Bump JNA 5.13.0 -> 5.19.1 for 16 KB page-size support (bindings) (60fa22c)
- Align Android .so to 16 KB pages for Google Play (bindings) (531e05c)
- Harden both relay bridges (third review pass) (bindings) (a666091)
- Stop the iOS bridge leaking sessions, racing sends (bindings) (6a64dd5)
- Plane-tag the android tracker, close socket races (bindings) (8f2b423)
- Gate control ops on hop count, bound relay retry loops (protocol) (cfacd0d)
- Harden both relay bridges (second review pass) (bindings) (3ee4d94)
- Require an outstanding registration for the relay sync ack (protocol) (21a7de6)
- Stop treating a local socket write as relay acceptance (bindings) (2c0ac68)
- Keep relay verdicts authoritative over late confirms (protocol) (886d400)
- Give iOS the stale-socket hardening Kotlin already got (bindings) (b0c8779)
- Serialize iOS control-op sends, mirror bridge fixes (bindings) (d3c03d7)
- Harden the Android relay bridge (review fixes) (bindings) (2621309)
- Scope relay-derived signals to the internet path (protocol) (63664f9)
- Lock bridge helpers, commit translator state post-write (bindings) (8eea294)
- Treat relay DeliveryError as authoritative for welcomes (protocol) (4a24b37)
- Only classify self-originated frames as internet control ops (protocol) (95d2fbd)
- Classify recipient-unreachable send failures as per-peer no-carrier (protocol) (032bded)
- Never mark groups relay-synced on enqueue (protocol) (e3a4c11)
- Match Android's strict typing check on iOS (bindings) (56bed49)
- Close the relay-dispatch and transport-dedup race holes (protocol) (8059013)
- Close three more holes in the welcome-race buffers (protocol) (5b90495)
- Close review holes in the welcome-race buffering (protocol) (eb4d5e8)
- Plug eviction and TTL holes in the welcome-race buffers (protocol) (8d4a5e1)
- Require the typing field on relay TypingUpdate events (bindings) (baf39c2)
- Buffer welcome-racing commits and bound the pending buffers (protocol) (e4bad9c)
- Buffer group messages that outrun their Welcome or commit (protocol) (7e8f80a)
- Classify send-path input validation as InvalidArgument (protocol) (e74ae8a)
- Stop double-prefixing transport send failures (uniffi) (f5e8e5e)
- Make the error taxonomy hold at the edges it leaked (bindings) (75a26ac)
- Map GroupNotFound in SessionStateError::classify (protocol) (de7acfe)
- Classify resource-exhaustion chunk rejections as InvalidState (uniffi) (d62c39e)
- Map SendFailed to a typed rejection code (bindings) (60e289b)
- Finish the GroupNotFound and send-path classification (uniffi) (734499b)
- Return GroupNotFound for admin ops on missing groups (protocol) (9b7b79c)
- Reject out-of-range BLE fragment indices (transport) (0be3871)
- Bound BLE fragment reassembly on the receive path (transport) (2a9a188)
- Bound the plaintext-receive warning set (protocol) (2b5eea9)
- Forget rejected messages so replays are never re-ACKed (protocol) (af92d91)
- Gate inbound plaintext text through require_encryption (protocol) (4bec083)
- Clear core discovery tracking on WiFi Direct disconnect (uniffi) (306ca76)
- Evict stale known_peers via TTL sweep and LRU at capacity (protocol) (42242cc)
- Route all NeighborDiscovered paths through the core discovery hook (uniffi) (cfd8afd)
- Reject non-UTF-8 decrypted payloads (protocol) (6f6bfe8)
- Honor allow_relay in Auto mode, unhardcode relay filter (router) (3acf606)
- Clamp adaptive-TTL device count before u8 cast (router) (443af12)
- Don't hold the callback mutex while invoking it (transport) (d212ddc)
- Refresh the cached Nostr pubkey and retry secret persistence(0e7c6cb)
- Stop deriving the Nostr signing key from device_id (transport) (bd1cc13)
- Default require_encryption to true across the FFI (bindings) (67202f7)
- Make encryption fail-closed by default (protocol) (941f3c7)
- De-flake bloom filter high-volume test (reliability) (36a984a)
- Validate GroupId::for_session inputs (mls) (457e2f4)
- Validate wire inviter ids before they become storage keys (mls) (c6fc090)
- Security-reject spoofed group messages instead of ACKing them (protocol) (3b9774c)
- Enforce MLS-authenticated sender on decrypt (SEC-M1) (mls) (59056e3)
- Bind imported key packages to the claimed identity (SEC-M5) (mls) (00b781c)
- Validate GroupId at construction and deserialization (SEC-M2) (mls) (92bd749)
- Clamp retry backoff before cast and unify the formula (#129) (reliability) (26d5503)
- Bound the file-transfer receive path (SEC-H2) (#128) (protocol) (3466ad5)
- Encrypt media and file transfers through MLS (SEC-H1) (#127) (protocol) (3f03ecc)
Refactoring
- Extract LegacyRelayMessage; pin the frame shape (bindings) (3cd0b6f)
- Prune unwired InternetTransport reconnect/heartbeat/handle API (transport) (4ff4af0)
- Delete dead fallback queues; race-free internet status change (uniffi) (0b72521)
- Extract the iOS rejection mapping for parity tests (bindings) (0a5720c)
- Extract shared promise-rejection error mapping (bindings) (0c719ca)
- Dedupe the group-existence check into a helper (protocol) (635091f)
- Typed errors for FileChunk::from_bytes and GroupRole parsing (protocol) (38bd2c5)
- Typed IdValidationError for validate_id_chars (core) (cfaf926)
- Take start/stop by &self and drop the transport mutex (transport) (12ee87b)
- Dispatch transport lifecycle through the trait (uniffi) (820aa30)
- Put the platform-bridge lifecycle on the trait (transport) (c5d2888)
- Delete the dead record_ack_received path (reliability) (218af14)
- Recover poisoned locks instead of panicking (transport) (285c233)
- Add poison-recovering lock extension traits (core) (ef6f941)
- Delete the never-wired congestion controller (router) (684f9e6)
Documentation
- Fix the native MLS snippets this guide left half-rotted(eaaf77a)
- Fix rotted native integration guides and dead security contact(92bb88f)
- True up the parity docs to the as-shipped semantics(e9b4a7e)
- Stop the parity plan lying about shipped semantics(b20097e)
- True up the parity docs and the welcome-event contract(9190c40)
- True up the raw-channel JSDoc and record the admin-gating contracts(591f0db)
- Record implemented WI-1 semantics and conn-request truth (spec) (91828b1)
- Relay-transport parity spec (validated) and implementation plan(71bb49b)
- Stop claiming FFI error messages are unchanged(3dc63ba)
- Document the FFI error-taxonomy contract change(b155d16)
- Stop pretending this crate does I/O (transport) (c9d3f5e)
- Document the fail-closed encryption default(5dd111d)
- Extend changelog for MLS auth-hardening follow-ups(c47d5e5)
- Add changelog entry for MLS auth hardening (SEC-M1/M2/M5)(9743170)
- Add status badges to the README (#126)(1a6b92a)
Testing
- Pin the control-op registry; make unhandled ops observable (protocol) (7090fcc)
- Actually run the iOS test mirrors (bindings) (6182979)
- Extract relay timestamp parsing and actually test it (bindings) (2428707)
- Cover the u64 header EOF path in FileChunk::from_bytes (protocol) (fbbf136)
- Pin variant-level contracts for the new typed errors(018ac05)
- Pin per-peer warnings and pre-MLS-init rejection (protocol) (edc862e)
- Pin drain-before-notify ordering against redundant Welcome re-arm (uniffi) (a345146)
Miscellaneous
- Release mesh-sdk v0.12.0 (bindings) (fdfd997)
- Bump mesh-sdk version to 0.11.1 (bindings) (aee6d51)
- Cargo fmt(a666f06)
- Regenerate Python bindings for presence surface (uniffi) (179de3f)
- Strip dependency debuginfo so the dev loop stops thrashing(12b23e9)
- Satisfy clippy 1.97 question_mark lint in reassemble(370214d)
- Fix clippy 1.95 lints failing the workspace gate(f8d1a38)
- Bump declared MSRV from 1.70 to 1.87 to match reality(4b9ad1d)
Build
- Ship the relay-parity Swift sources in the podspec (bindings) (d33d403)