Skip to main content

max / synckit

Exorcise sweep: rewrite connective dashes in synckit comments and docs Last of the uncommitted sweep. Not my edits; verified rather than authored. Comment and doc prose only, across both crates: Cargo.toml dependency rationale, the synckit-config module and spec headers, store/config.rs, the architecture doc, and the root README. No code changes. synckit-client 514 tests passed, synckit-config 13 passed, 0 failed. Note for future sweeps: comment prose is now exempt from the dash rule (ruled 2026-07-27, recorded in brand.md and both exorcise skip lists), so this class of edit should not recur. Existing conversions stay; there is no revert and no further tree-wide pass.
Co-Authored-By
Claude Opus 5 (1M context) <noreply@anthropic.com>
Author: Max Johnson <me@maxj.phd> · 2026-07-27 21:17 UTC
Signed with PGP, not checked
Commit: 08b1f868f6179b7cf8a40b9f73bd12005c88a360
Parent: 363928b
7 files changed, +18 insertions, -18 deletions
M README.md +3 -3
@@ -6,16 +6,16 @@
6 6 independently. Two standalone crates, no root workspace (each builds on its own,
7 7 matching the ecosystem convention):
8 8
9 - - **`synckit-client`** — the sync SDK: transport, crypto, the declarative
9 + - **`synckit-client`**, the sync SDK: transport, crypto, the declarative
10 10 `SyncStore` engine over SQLite. Internal; consumed by path or git dependency,
11 11 never published to crates.io.
12 - - **`synckit-config`** — a local key/value settings store with per-key sync
12 + - **`synckit-config`**, a local key/value settings store with per-key sync
13 13 postures. The store half of portable config; usable with no network, so a
14 14 no-sync consumer (a TUI remembering a theme) links it without the SDK. The
15 15 sync adapter that turns a `ConfigSpec` into a `SyncTable` lives in
16 16 `synckit-client` behind its `store` feature.
17 17
18 18 The synckit **server** still lives in the MNW server. Splitting it into a
19 - standalone service on its own VPS is a separate, later effort — see the wiki
19 + standalone service on its own VPS is a separate, later effort. See the wiki
20 20 note `mnw-strategy-synckit-vps-separation`, triggered by the first external
21 21 developer.
@@ -26,7 +26,7 @@
26 26 rand = "0.10"
27 27 base64 = "0.22"
28 28 zeroize = "1"
29 - # X25519 ECDH — the only asymmetric primitive in the crate, used solely by the
29 + # X25519 ECDH: the only asymmetric primitive in the crate, used solely by the
30 30 # group-key layer (`identity.rs`) to seal a Group Content Key to a member's public
31 31 # key. Pure-Rust (curve25519-dalek), no aws-lc/ring. Deliberately just the curve op:
32 32 # the GCK itself is sealed with the XChaCha20-Poly1305 above, not a sealed-box crate.
@@ -39,7 +39,7 @@
39 39
40 40 # HTTP
41 41 # rustls-no-provider: rustls TLS with the OS-native trust store (rustls-platform-verifier),
42 - # no bundled crypto provider — the consuming app installs one process default (ring).
42 + # no bundled crypto provider, so the consuming app installs one process default (ring).
43 43 reqwest = { version = "0.13", default-features = false, features = ["json", "rustls-no-provider", "stream", "form", "charset", "http2", "system-proxy"] }
44 44 bytes = "1"
45 45 tokio = { version = "1", features = ["rt-multi-thread", "macros", "time", "fs", "io-util"] }
@@ -84,7 +84,7 @@
84 84 # Self dev-dependency: turns on the `testing` feature for this crate's own
85 85 # unit/integration test builds without leaking it into a consumer's default set.
86 86 # `default-features = false` so it only ADDS `testing` to whatever the test run
87 - # already selected — under a plain `cargo test` the package still builds with its
87 + # already selected. Under a plain `cargo test` the package still builds with its
88 88 # own defaults (keychain + store), but `cargo test --no-default-features` can turn
89 89 # keychain OFF (making `keystore::store_key` the no-op stub) to run the keychain-
90 90 # free rotation orchestration test below.
@@ -545,7 +545,7 @@
545 545 SQLite file** (given a path or a connection factory). Under WAL, which all three
546 546 apps already use, the engine's short read/apply transactions coexist with the
547 547 app's own pool on the same file. The app's domain code is untouched; the sync
548 - engine simply becomes another connection that reads `sync_changelog` and writes
548 + engine becomes another connection that reads `sync_changelog` and writes
549 549 the domain tables under the `applying_remote` guard. This also matches audiofiles
550 550 exactly and removes GO/BB's async-sync code entirely.
551 551
@@ -791,7 +791,7 @@
791 791
792 792 ### What GO proved about the design
793 793
794 - - **Confirmed: credential exclusion collapses.** The single most bespoke piece of
794 + - **Confirmed: credential exclusion collapses.** The single most hand-rolled piece of
795 795 GO's apply layer (`apply_email_account_upsert`, its own INSERT-with-`password=''`
796 796 and 16-column ON CONFLICT) is fully expressed by `preserve_local` +
797 797 `insert_defaults`. No per-table override function survives. This was the strongest
@@ -4,8 +4,8 @@
4 4 //! does not sync. A [`ConfigStore`] is a SQLite key/value table an app reads and
5 5 //! writes with no network in sight; a [`ConfigSpec`] declares which of those keys
6 6 //! may cross the sync boundary. `synckit-client` turns a spec into a
7 - //! `SyncTable`, but nothing here depends on it, so a no-sync consumer — the Alloy
8 - //! console remembering a theme — links this crate and not the sync runtime.
7 + //! `SyncTable`, but nothing here depends on it, so a no-sync consumer (the Alloy
8 + //! console remembering a theme) links this crate and not the sync runtime.
9 9 //!
10 10 //! ## Why this is its own crate, and why it is SQLite
11 11 //!
@@ -16,7 +16,7 @@
16 16 //! different keys must both survive (row-level HLC merge, which a whole-file blob
17 17 //! cannot do), and some keys must never sync at all (see posture). Rows are what
18 18 //! buy both. A text file would need a projection layer and a sidecar for the
19 - //! per-key merge metadata — SQLite by the back door. Design note:
19 + //! per-key merge metadata: SQLite by the back door. Design note:
20 20 //! `synckit-config-design` in the wiki.
21 21 //!
22 22 //! ## Posture, and why it fails closed
@@ -13,7 +13,7 @@
13 13 ///
14 14 /// The default is [`Local`](Posture::Local), and so is the answer for any key a
15 15 /// spec does not mention: see [`ConfigSpec::posture`]. That is the whole safety
16 - /// property — a key crosses the sync boundary only when someone wrote down that
16 + /// property: a key crosses the sync boundary only when someone wrote down that
17 17 /// it should.
18 18 #[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
19 19 pub enum Posture {
@@ -46,8 +46,8 @@
46 46 /// The keys a config knows, and their postures.
47 47 ///
48 48 /// Declared as a `const` per app: the table it lives in, and every key with its
49 - /// posture. Only [`Synced`](Posture::Synced) keys need listing for correctness —
50 - /// an unlisted key reads as [`Local`](Posture::Local) — but listing the local
49 + /// posture. Only [`Synced`](Posture::Synced) keys need listing for correctness
50 + /// (an unlisted key reads as [`Local`](Posture::Local)), but listing the local
51 51 /// ones too documents the surface and lets a test assert the set is complete.
52 52 #[derive(Debug, Clone, Copy)]
53 53 pub struct ConfigSpec {
@@ -80,7 +80,7 @@
80 80 ///
81 81 /// **Fail-closed: an undeclared key is [`Local`](Posture::Local).** This is
82 82 /// the rule the whole sync boundary rests on. A key nobody classified never
83 - /// replicates, so forgetting to name a new local path does not leak it — the
83 + /// replicates, so forgetting to name a new local path does not leak it. The
84 84 /// failure of omission keeps data home rather than sending it.
85 85 pub fn posture(&self, key: &str) -> Posture {
86 86 self.keys
@@ -1,6 +1,6 @@
1 1 //! The local key/value store: a SQLite table an app reads and writes.
2 2 //!
3 - //! No network, no posture in sight — posture governs what *syncs*, and this is
3 + //! No network, no posture in sight. Posture governs what *syncs*, and this is
4 4 //! the store that exists whether or not an app syncs at all. It creates one
5 5 //! table, `key TEXT PRIMARY KEY, value TEXT NOT NULL`, and offers get/set/unset
6 6 //! over it. A no-sync consumer (the Alloy console) uses only this; a syncing one
@@ -5,7 +5,7 @@
5 5 //! terms. An app calls [`config_sync_table`] to fold config into its
6 6 //! [`SyncSchema`] and [`install_policy`] once at open to seed the filter the
7 7 //! generated trigger reads. After that the app's `ConfigStore` writes replicate
8 - //! transparently — the consumer never learns whether sync is wired.
8 + //! transparently: the consumer never learns whether sync is wired.
9 9 //!
10 10 //! ## The posture filter, and why it is an allowlist
11 11 //!
@@ -18,7 +18,7 @@
18 18 //! ```
19 19 //!
20 20 //! An **allowlist**, not a denylist, and that is the security property. A key
21 - //! with no policy row does not match, so it never enters the changelog — an
21 + //! with no policy row does not match, so it never enters the changelog: an
22 22 //! unclassified key stays on the device. audiofiles reached the same predicate
23 23 //! the hard way: its earlier `key != 'loose_files'` denylist never covered
24 24 //! `mirror_path`/`mirror_enabled`, letting a hostile server steer a local write