- tines-core's crate docs carry the spec §8 compatibility policy, as the
README does.
- tines-bt: the module and BluerRadio::new docs claimed an optional or
empty allowlist. The allowlist is exactly the configured peer (F3).
- tines: the poll loop called Store::flush "infallible". It returns a
Result, and a failure is logged and retried on the next schedule.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Decision K (spec §5): the local capacities and timings are defaults that
will become configuration, so they are `pub(crate)`. The wire constants
stay public.
- MAX_PEERS, SUMMARY_INTERVAL_MS, REASSEMBLY_TIMEOUT_MS, SEND_QUEUE_CAP,
MIN_MTU, EVENT_QUEUE_CAP, DROP_TABLE_CAP, BCAST_SENT_CAP, ACK_BUFFER_CAP
and PEER_IDLE_MS are now `pub(crate)`; a compile_fail doctest pins it.
- MIN_MTU's doc claimed it was the floor below which a fragment has no
room. It is only the frag sweep's lower bound (BLE ATT's 23). The real
floors are now stated on `Transport::mtu` and pinned by
`consts::tests::mtu_floors`: 85 to carry every valid observation, 66 to
fragment at all, 35 for an Ack, 26 for a summary.
- tines-bt caps live connections with its own MAX_PEERS (8).
- tines-sim's props mirror MAX_PEERS/SEND_QUEUE_CAP, checked against core
through the hidden `conformance` module; the fuzz twin reads it there.
- node.rs: drain_events' rustdoc no longer links the now-private consts.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Task 8 of the fleet-deployment plan. Adds the tines-bt crate: a real
`Transport` over the `bluer` crate (D-Bus BlueZ).
- `Addr` = peer's advertised `NodeId`, so identity survives BLE
address rotation; advertising payload (flags + 16-bit service UUID +
NodeId in service data) fits legacy 31-byte EIR (`advertise()`).
- `BtTransport` drops any inbound frame whose `from` differs from the
connection's advertised NodeId (protocol violation at the transport;
core never sees a mismatch).
- Connection symmetry: the node with the numerically smaller NodeId is
the BLE central/initiator (`is_central`), independent of which side
opens the radio.
- `mtu()` reports the real L2CAP CoC MTU (falling back to the ATT MTU);
the transport does NOT split frames — core folds summaries/fragments
to `mtu()`.
- Radio I/O sits behind the narrow `Radio` trait (a `poll`-driven event
stream), so the pure logic (payload assembly, mismatch-drop, central
rule) is unit-tested with a mock radio and never needs hardware.
- `BluerRadio` drives the stack on a detached tokio task: powers the
adapter, advertises, monitors for the service UUID, opens an L2CAP
byte pipe, and surfaces inbound bytes tagged with the peer NodeId.
Adds `tests/adv.rs` (8 mock-Radio integration tests covering the 31-byte
limit, NodeId round-trip, MTU clamp, mismatch-drop, per-frame MTU, and
central rule). Added to workspace members; workspace CI (fmt, doc,
test, clippy -D warnings) is green.