max / synckit-client
git clone https://makenot.work/git/max/synckit-client.git
git clone git@ssh.makenot.work:max/synckit-client.git
| Name | Size | |
|---|---|---|
| docs/ | ||
| src/ | ||
| tests/ | ||
| .gitignore | 86 B | |
| Cargo.lock | 58.9 KB | |
| Cargo.toml | 984 B | |
| LICENSE | 4.4 KB | |
| README.md | 3.0 KB |
README
synckit-client
End-to-end encrypted cloud sync SDK for Rust applications, built for the MNW SyncKit server.
All row data and binary blobs are encrypted client-side (XChaCha20-Poly1305) before leaving the device. The server only ever stores ciphertext.
Features
- E2E encryption – XChaCha20-Poly1305 with Argon2id key derivation (64 MB, 3 iterations)
- OS keychain integration – master key cached in macOS Keychain, Linux secret-service, or Windows Credential Manager
- Blob encryption – binary files encrypted with fixed 40-byte overhead (no base64 expansion)
- Retry with backoff – transient failures (network, 5xx, 429) retried up to 3 times with exponential delay
- OAuth2 PKCE – browser-based auth flow alongside email/password
- Token expiry detection – client-side JWT check with 30-second buffer
Quick Start
use synckit_client::{SyncKitClient, SyncKitConfig, ChangeEntry, ChangeOp};
use chrono::Utc;
let client = SyncKitClient::new(SyncKitConfig {
server_url: "https://makenot.work".into(),
api_key: "your-api-key".into(),
});
// Authenticate
let (user_id, app_id) = client.authenticate("user@example.com", "password").await?;
// Set up encryption (first device)
client.setup_encryption_new("password").await?;
// Register this device
let device = client.register_device("MacBook Pro", "macos").await?;
// Push encrypted data
let cursor = client.push(device.id, vec![
ChangeEntry {
table: "tasks".into(),
op: ChangeOp::Insert,
row_id: uuid::Uuid::new_v4().to_string(),
timestamp: Utc::now(),
data: Some(serde_json::json!({"title": "Buy milk"})),
},
]).await?;
// Pull and auto-decrypt
let (changes, cursor, has_more) = client.pull(device.id, 0).await?;
Crate Structure
| File | Role |
|---|---|
lib.rs | Crate root, re-exports, doc example |
client.rs | SyncKitClient – HTTP methods, retry logic, token expiry detection |
crypto.rs | Key derivation (Argon2id), key wrapping, per-entry and per-blob encrypt/decrypt |
error.rs | SyncKitError enum (10 variants: HTTP, server, JSON, crypto, keychain, auth) |
keystore.rs | OS keychain read/write/delete, feature-gated with no-op stubs |
types.rs | Wire protocol types (ChangeEntry, ChangeOp, Device, SyncStatus) |
Feature Flags
| Flag | Default | Description |
|---|---|---|
keychain | on | OS keychain storage via the keyring crate. Disable with default-features = false for headless/CI environments. |
Security Properties
- Server-zero-knowledge – the server never receives the plaintext master key or user data
- Key zeroization – volatile writes clear the master key from memory on drop
- Random salt per wrap – re-wrapping with the same password produces a different envelope
- Minimum ciphertext validation – decryption rejects inputs shorter than 40 bytes (24-byte nonce + 16-byte tag)
- No key material in logs – tracing events never include key bytes or ciphertext
License
PolyForm Noncommercial 1.0.0