From a85f57a869ca11efcf28d086d1b9168c6a7885b4 Mon Sep 17 00:00:00 2001 From: "K. Isom" Date: Wed, 21 Oct 2026 23:10:33 -0700 Subject: [PATCH] docs(core,hosts): crate-level Stability section; fix comments that contradict the code MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 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 --- tines-bt/src/transport.rs | 11 ++++++----- tines-core/src/lib.rs | 26 ++++++++++++++++++++++++++ tines/src/ipc.rs | 6 +++--- 3 files changed, 35 insertions(+), 8 deletions(-) diff --git a/tines-bt/src/transport.rs b/tines-bt/src/transport.rs index 1e0042dd..60b1c0be 100644 --- a/tines-bt/src/transport.rs +++ b/tines-bt/src/transport.rs @@ -32,8 +32,9 @@ //! //! Up to [`MAX_PEERS`] connections may be live at once, one per bound //! [`NodeId`]. A second connection to the same [`NodeId`] replaces the first. -//! The configured `peer` becomes an optional allowlist; empty means "any tines -//! advertiser". +//! Today the allowlist is exactly the configured `peer`, and frames and events +//! from any other peer are dropped; an optional allowlist (empty meaning "any +//! tines advertiser") is still to come (THREAT_MODEL.md F3). use std::collections::{BTreeMap, BTreeSet, HashMap}; use std::sync::{ @@ -266,9 +267,9 @@ impl BluerRadio { /// Start the `bluer`/BlueZ radio for a connection between `me` (this /// device) and `peer` (the peer's advertised [`NodeId`]). /// - /// `peer` is this node's allowlist: only that NodeId's connections are - /// accepted. With an empty allowlist the transport accepts any tines - /// advertiser. + /// `peer` is this node's whole allowlist: only that NodeId's connections + /// are accepted. (The radio loop treats an empty allowlist as "any tines + /// advertiser", but `new` never builds one; THREAT_MODEL.md F3.) pub fn new(me: NodeId, peer: NodeId) -> Self { let (event_tx, event_rx) = async_mpsc::unbounded_channel::(); let (send_tx, send_rx) = async_mpsc::unbounded_channel::<(NodeId, Vec)>(); diff --git a/tines-core/src/lib.rs b/tines-core/src/lib.rs index 9b5aee6b..1db0fb56 100644 --- a/tines-core/src/lib.rs +++ b/tines-core/src/lib.rs @@ -1,4 +1,30 @@ //! tines-core: content-defined Observation identity and shared-memory core. +//! +//! # Stability +//! +//! tines-core 1.0 guarantees, within the 1.x line: +//! +//! - **Wire:** every 1.x release speaks wire v1 ([`consts::WIRE_VERSION`]). +//! Only new optional frame variants may be added, plus new [`SigAlgo`] ids +//! and signature versions within the 64-byte [`consts::MAX_SIG`] budget. A +//! wire-v2 change, including any post-quantum signature or a +//! [`consts::MAX_FRAME`] above 1500, ships as tines-core 2.0. +//! - **Identity:** [`Observation::id`] never changes within a major version, +//! and should not change across majors unless the hash itself is broken. +//! - **API:** standard semver; MSRV bumps are minor. Public types are +//! `#[non_exhaustive]` where they may grow. A method added to [`Store`], +//! [`Transport`] or [`BeliefPolicy`] after 1.0 must have a default whose +//! behaviour is safe: it may lose performance or telemetry, never data or +//! custody. Wall-clock folds live in the opt-in [`WallClockStore`] trait, +//! not in [`Store`]. The `#[doc(hidden)]` `conformance` module is not part +//! of the API. +//! - **Local behaviour** (capacities, timings, scheduling order, which +//! candidate goes first) can change in a minor release as long as the +//! protocol properties hold: custody always keeps at least one holder, +//! receipts never shorten world state, and every frame fits +//! [`Transport::mtu`]. That's why the local constants are crate-private. +//! - **Signatures:** 1.0 carries them ([`Observation::sig`]); 1.1 signs and +//! verifies them, without breaking the wire or the API. #![no_std] #![deny(missing_docs)] diff --git a/tines/src/ipc.rs b/tines/src/ipc.rs index 4dc7e0b4..da7b1e53 100644 --- a/tines/src/ipc.rs +++ b/tines/src/ipc.rs @@ -266,9 +266,9 @@ where } } - // On a schedule: trim stale observations and flush the store. Flush is - // `LogStore::flush`, reached through `Node::flush(now)`, which delegates to - // `Store::flush` — the infallible durability boundary. + // On a schedule: trim stale observations and flush the store. `Node::flush` + // delegates to `LogStore`'s `Store::flush` impl, the durability point; a + // failure is logged and the next scheduled flush retries. if host.rounds >= POLL_CAP { host.rounds = 0; node.trim(&TrimPolicy::default(), host.clock.now());