Repository navigation
A fast path between online devices. On-remote format unchanged (bothy_format = 1); the new
signaling files are optional and 0.3 readers ignore them. The Python and Flutter packages
have their own changelogs.
Added
- Direct channels between online devices (
p2pfeature, on by default but inactive until
Config::p2p(P2pConfig)). While background sync runs, devices find each other through
signaling files on the remote and open a WebRTC data channel
(str0m; ICE with host and STUN candidates,
stun.l.google.comby default, no TURN).- After uploading a segment, a device sends it to its peers (up to 64 KiB, otherwise an
announcement), and they apply it at once. The remote stays the durable record: nothing
is sent before it is uploaded, and without a channel sync works as before. - Measured p50 from a write to the other device: 1.1 to 1.7 s, against about 30 s by
polling. Database::p2p_status()(also in the blocking API) withP2pStatus::discoveringand
per-peerPeerState.AutoSync::p2p_debounce(100 ms) is the write debounce while a channel is open.
Background sync polls every 3 s while peers are being found.- A failed attempt is retried after 15 s, doubling up to 10 minutes. A device whose
onlinefile could not be written retries after 15 s.
- After uploading a segment, a device sends it to its peers (up to 64 KiB, otherwise an
- Signaling files:
codec::keys::{KeyKind::Signal, SignalKind}
(<db_id>/signaling/<device_id>/{online-<hlc>,offer-<peer>-<hlc>,answer-<peer>-<hlc>}.json)
andcodec::signal. They are sealed in encrypted databases, so SDPs and IP addresses never
reach the remote in plain text. Conformance vectors:spec/vectors/signaling.json. - CLI:
sync --watch --p2p, with--stunor--no-stun, prints peer state changes.- The hidden
bench propagate(--peerfor a second local database, orbench echoon
another device) measures how long a write takes to reach another device.
Changed
- Drive: file ids are reserved 20 at a time, so most uploads need one request instead of two.
codec::keys::KeyKindis#[non_exhaustive].AutoSynchas a new field; struct literals need..AutoSync::default().- The
p2pfeature buildsaws-lc-sys(C) for str0m'saws-lc-rscrypto backend.
Security
- No
crypto-bigint0.5 (RUSTSEC-2026-0387): P2P uses str0m'saws-lc-rsbackend rather than
its RustCrypto one.
Packages
- crates.io:
bothy,bothy-cli,bothy-oauth - PyPI:
bothy0.4.0, abi3 wheels for CPython 3.9+ on Linux (x86_64, aarch64, armv7), macOS (universal2) and Windows (x64); seebindings/python/CHANGELOG.md - pub.dev:
bothy0.4.0; seebindings/flutter/CHANGELOG.md
Accepted live between the macOS CLI and the Flutter demo on an Android emulator, on one encrypted database (#71):
- 50 writes from the Mac reached the phone with p50 1.12 s, against about 30 s by polling.
- With the network cut, sync went on through Drive.
- The channel came back about 1.5 minutes after the network did.
- No plain-text addresses or SDPs reached the remote.