[package] name = "synckit-client" version = "0.6.0" edition = "2024" description = "SyncKit client SDK with end-to-end encryption" license-file = "LICENSE" [features] default = ["keychain", "store"] keychain = ["dep:keyring"] # The higher-level SyncStore engine (owns a rusqlite connection to the app's DB). # Default-on so app consumers get it for free; a consumer that only needs the # transport/crypto SDK (e.g. mnw-cli, which sets `default-features = false`) skips # it and avoids compiling bundled SQLite. store = ["dep:rusqlite", "dep:synckit-config"] # Exposes test-only constructors (`set_master_key_raw`, `with_http_client`) that # bypass key derivation. Enabled automatically for this crate's own test builds # via the self dev-dependency below; never part of `default`, so a real consumer # cannot reach a raw-key injection point. testing = [] [dependencies] # Encryption chacha20poly1305 = "0.11" argon2 = "0.5" rand = "0.10" base64 = "0.22" zeroize = "1" # X25519 ECDH — the only asymmetric primitive in the crate, used solely by the # group-key layer (`identity.rs`) to seal a Group Content Key to a member's public # key. Pure-Rust (curve25519-dalek), no aws-lc/ring. Deliberately just the curve op: # the GCK itself is sealed with the XChaCha20-Poly1305 above, not a sealed-box crate. # `static_secrets` enables the reusable `StaticSecret` (a member's long-lived key). x25519-dalek = { version = "2", default-features = false, features = ["static_secrets", "zeroize"] } # PKCE (OAuth2) challenge hashing sha2 = "0.11" hex = "0.4" # HTTP # rustls-no-provider: rustls TLS with the OS-native trust store (rustls-platform-verifier), # no bundled crypto provider — the consuming app installs one process default (ring). reqwest = { version = "0.13", default-features = false, features = ["json", "rustls-no-provider", "stream", "form", "charset", "http2", "system-proxy"] } bytes = "1" tokio = { version = "1", features = ["rt-multi-thread", "macros", "time", "fs", "io-util"] } tokio-stream = "0.1" # Serialization serde = { version = "1", features = ["derive"] } serde_json = "1" chrono = { version = "0.4", features = ["serde"] } uuid = { version = "1", features = ["v4", "serde"] } # OS keychain (optional) keyring = { version = "4", optional = true } # URL encoding urlencoding = "2" # Unicode unicode-normalization = "0.1" # Synchronization parking_lot = "0.12" # Error handling & logging thiserror = "2" tracing = "0.1" # SyncStore engine (feature = "store"). Owns the app's SQLite connection. Bundled # so no system libsqlite is needed; `functions` to register the `hash_row_id` UDF. rusqlite = { version = "0.39", features = ["bundled", "functions"], optional = true } # The local config store (posture types + KV store). The config sync adapter # (src/store/config.rs) turns a ConfigSpec into a SyncTable. Path dep: sibling in # the MNW tree, versioned together. synckit-config = { path = "../synckit-config", optional = true } [dev-dependencies] wiremock = "0.6" # reqwest is built `rustls-no-provider`, so real consumers install a rustls crypto # provider at startup (audiofiles installs ring). The test suite has no such app, so # it installs ring itself before building any client. Dev-only: never in a consumer build. rustls = { version = "0.23", default-features = false, features = ["ring"] } # Self dev-dependency: turns on the `testing` feature for this crate's own # unit/integration test builds without leaking it into a consumer's default set. # `default-features = false` so it only ADDS `testing` to whatever the test run # already selected — under a plain `cargo test` the package still builds with its # own defaults (keychain + store), but `cargo test --no-default-features` can turn # keychain OFF (making `keystore::store_key` the no-op stub) to run the keychain- # free rotation orchestration test below. synckit-client = { path = ".", default-features = false, features = ["testing"] } [lints.rust] unused = "warn" unreachable_pub = "warn" [lints.clippy] pedantic = { level = "warn", priority = -1 } # Allow-list tuned from a measured breakdown across server/multithreaded/pter # (2026-07-22). These are the high-churn / low-signal pedantic lints; everything # else in `pedantic` stays a warning. Keep this block identical across repos. module_name_repetitions = "allow" # Doc lints. No docs-completeness push is underway. missing_errors_doc = "allow" missing_panics_doc = "allow" doc_markdown = "allow" # Numeric casts. Endemic and mostly intentional in size and byte math. cast_possible_truncation = "allow" cast_sign_loss = "allow" cast_precision_loss = "allow" cast_possible_wrap = "allow" cast_lossless = "allow" # Subjective structure and style nags. High churn, low signal. must_use_candidate = "allow" too_many_lines = "allow" struct_excessive_bools = "allow" similar_names = "allow" items_after_statements = "allow" single_match_else = "allow" # Frequent false-positives in TUI and router-heavy code. match_same_arms = "allow" unnecessary_wraps = "allow" type_complexity = "allow"