Commit Graph
12 Commits
Author SHA1 Message Date
osobh bb299f4b77 chore: commit local changes before node reformat
CI / Publish dry-run (clawsync-core) (push) Has been cancelled
CI / Test (stable) (push) Has been cancelled
CI / Clippy + fmt (push) Has been cancelled
CI / MSRV (1.85) (push) Has been cancelled
2026-05-10 13:58:39 -07:00
osobhandClaude Opus 4.7 1bf6cffe0e clawsync-transport: SealedFile/SealedFileAck variants + mTLS PEM constructors
Adds the wire surface and the cert-loading constructors that
omni-sync's QuicTransport needs for sealed-day replication to a
peer Garage node.

Protocol additions (rkyv discriminants are positional — appended
at the end, never inserted):

- `SyncMessage::SealedFile { peer_name, payload }`: sealed `.h5`
  delivery from `omni-sync` clients (omni-cortex daemons
  replicating sealed-day Working / Episodic / Semantic tier
  files to a peer).
- `SyncMessage::SealedFileAck { peer_name, bytes, blake3_hex }`:
  receiver-computed BLAKE3 acknowledgement so the sender can
  verify the bytes landed intact.

QuicConfig constructors for production mTLS:

- `client_with_pem(client_cert, client_key, server_ca)` — loads
  the operator's mTLS leaf identity + the CA whose-issued server
  certs the client trusts. Builds a real rustls `ClientConfig`
  via `with_client_auth_cert`. Server config field gets a
  placeholder (never consumed by `quic_connect`).
- `server_with_pem(server_cert, server_key, client_ca)` — mirror
  for the receive side. Real rustls `ServerConfig` with
  `WebPkiClientVerifier::builder(roots).build()` +
  `with_client_cert_verifier` (mutual auth: clients without a
  CA-issued cert fail the handshake) + `with_single_cert`.

Validated by `omni-sync`'s D193 production-mTLS round-trip test:
rcgen-generates CA + matching server cert + matching client
cert, writes PEMs to a tempdir, spawns a `QuicServer` with
`server_with_pem`, drives a real `QuicTransport` production-mode
client through `SealedFile` → `SealedFileAck` with mutual cert
verification.

Also includes a `rustls-pemfile = "2.2"` dep + ambient
`cargo fmt` line-collapsing in `framed.rs` and `peer.rs` from
when the workspace was reformatted.

Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
2026-05-02 05:31:32 -07:00
osobhandClaude Sonnet 4.6 6d2eb5a1db feat: QUIC backend tests, diff command, clippy/doc fixes, QUIC push race fix
- Add QuicSyncBackend + quic_scheduler; fix push stream/close race by
  waiting for peer close instead of calling close_and_drain() on the
  client side (SyncComplete stream was racing CONNECTION_CLOSE)
- Add PipeWriteHalf::shutdown_push() for client-sends-last QUIC paths;
  use it in cmd_push so the server can process SyncComplete before the
  connection tears down
- Add SshSyncBackend + ssh_scheduler with subprocess integration tests
- Add clawsync diff command with --porcelain flag and subprocess tests
- Add QUIC subprocess push/pull integration tests
- Fix clippy --tests violations across 5 crates
- Fix broken intra-doc links (reader.rs, lib.rs, scheduler.rs)
- Rewrite crate READMEs; update BENCHMARKS.md with clawsync-fs CDC row

653 tests, 0 failures.

Co-Authored-By: Claude Sonnet 4.6 <[email protected]>
2026-04-06 22:40:31 -05:00
osobhandClaude Sonnet 4.6 85b6edbdff feat: SSH transport — clawsync sync user@host:path without pre-running server
Adds generic framed I/O transport (FramedReader/FramedWriter over any
AsyncRead/AsyncWrite) and a StreamPeer backed by boxed I/O, enabling
two new modes:

SSH client mode:
  clawsync sync <local> [user@]host:path
  Detects SSH syntax (@ or non-numeric port), spawns
  `ssh user@host clawsync serve-fs path --stdio`, and uses the child's
  stdin/stdout as the sync protocol channel. No pre-running server needed.

stdio server mode (--stdio flag on serve-fs / serve-all):
  clawsync serve-fs <dir> --stdio
  Reads/writes the sync protocol on stdin/stdout instead of binding TCP.
  Suppresses the startup message (stdout is the protocol channel).
  Used automatically by SSH clients; also usable in scripts/containers.

Transport layer (clawsync-transport):
  - New framed.rs: FramedReader<R>, FramedWriter<W>, StreamPeer, split halves
  - SyncPeer::Stream variant; into_pipe_halves() splits into StreamReadHalf/WriteHalf
  - PipeReadHalf::Stream, PipeWriteHalf::Stream for pipelined W=16 sessions

CLI (clawsync-cli):
  - ParsedRemote enum; parse_remote_target() handles both TCP and SSH syntax
  - connect_remote() dispatches to TCP/QUIC or ssh_connect()
  - cmd_sync and cmd_watch use connect_remote() — SSH works transparently
  - cmd_serve_fs and cmd_serve_all gain --stdio flag
  - 2 integration tests: SSH (skipped without CLAWSYNC_TEST_SSH=1), stdio no-panic

Co-Authored-By: Claude Sonnet 4.6 <[email protected]>
2026-04-05 13:24:44 -05:00
osobhandClaude Sonnet 4.6 172a7e95eb feat: add pull-fs command (reverse sync — fetch from remote to local)
Adds FsSyncPullClient + FsSyncPullServer implementing the reverse
direction of the existing sync protocol. Client sends a FsDirPullRequest
with its local manifest; server diffs against its own tree, sends
FsDirNeed + pipelined FsCdcData (W=16), client reconstructs with atomic
write+rename and mtime preservation, replies with FsFileAck per file.

- New protocol variant FsDirPullRequest (index 22, rkyv append-only)
- FsSyncPullClient and FsSyncPullServer in session.rs with 4 unit tests
- CLI pull-fs subcommand (remote host:port/path, local dir, --delete, --quic)
- 6 integration tests: cold copy, warm no-op, incremental, delete/no-delete, QUIC

Co-Authored-By: Claude Sonnet 4.6 <[email protected]>
2026-04-05 12:20:17 -05:00
osobhandClaude Sonnet 4.6 ad479324ca feat(fs): preserve source mtime on synced files + document deprecated protocol variants
- Server restores client's modification time (from FsManifestEntry.mtime) after
  atomic write+rename, so tools that check mtimes (make, backup software, rsync)
  don't see every synced file as freshly written. Best-effort: silently ignored on
  FAT32 and read-only filesystems.
- Add session unit test verifying mtime is preserved within ±2s tolerance.
- Document FsCdcRequest/FsCdcNeed variants as deprecated stubs kept only because
  rkyv's append-only rule forbids removal; current protocol embeds server chunks
  directly in FsDirNeed, eliminating the per-file sub-exchange round-trip.

Co-Authored-By: Claude Sonnet 4.6 <[email protected]>
2026-04-05 12:01:43 -05:00
osobhandClaude Sonnet 4.6 0ed2f5054f feat(quic): fix QUIC connection teardown + add FS QUIC integration tests
- Add QuicConfig::insecure() with NoopVerifier for subprocess integration
  tests where server/client generate independent self-signed certs
- Fix QUIC endpoint lifetime bug: store _endpoint in QuicConnection so
  quinn's endpoint outlives its connection (previously dropped on return)
- Add install_crypto_provider() to transport lib; call it in main() to
  satisfy rustls 0.23's explicit install_default() requirement
- Add QuicConnection::wait_for_peer_close(): server passively awaits
  client close instead of racing to send CONNECTION_CLOSE before
  in-flight streams (FsDirComplete, FsFileAck) reach the client
- Add SyncPeer::quic_conn_clone() + update shutdown/drain to use
  close_and_drain (client) vs wait_for_peer_close (server)
- Add 3 QUIC FS sync integration tests: cold-copy, warm-noop, incremental

Co-Authored-By: Claude Sonnet 4.6 <[email protected]>
2026-04-05 09:50:26 -05:00
osobhandClaude Sonnet 4.6 ac8969fb5d feat: add --dry-run to clawsync sync
- protocol: add dry_run: bool to FsDirManifest
- session: FsSyncClient::with_dry_run() sets the flag; run() handles
  FsDirDryRun response and returns would_add/modify/remove in SyncStats
  with bytes_transferred=0 and no files written
- session (server): if client sends dry_run=true, compute diffs and send
  FsDirDryRun instead of FsDirNeed; return without writing anything
- cli: --dry-run flag on `sync`; print +/~/- prefix per path and summary
- tests: 4 new unit tests covering add, modify, unchanged, and
  allow_delete+remove scenarios

Co-Authored-By: Claude Sonnet 4.6 <[email protected]>
2026-04-05 09:23:38 -05:00
osobhandClaude Sonnet 4.6 f1bdf921be Complete mmap transport: functional MmapSender/MmapReceiver + SyncPeer::Mmap
MmapSender and MmapReceiver were structural stubs with only open() methods.
Now each holds its own MmapMut view of the channel file and implements full
ring-buffer send/recv using AtomicU64 Acquire/Release stores for correct
cross-process visibility.

Extracted shared ring_send/ring_recv logic used by all three types
(MmapChannel, MmapSender, MmapReceiver). Replaced plain write_u64/read_u64
header accessors with atomic_store/atomic_load in the hot path; plain
helpers retained for one-time initialisation in create().

SyncPeer gains a Mmap { send_ch, receiver } variant; PipeWriteHalf and
PipeReadHalf gain Mmap arms. Async SyncPeer::send/recv/into_pipe_halves
wrap the blocking spin-wait calls with tokio::task::block_in_place.

Added 5 new mmap tests: sender_receiver_open_same_file, roundtrip,
multiple_messages, ring_wraps, cross_thread (two-thread SPSC).

Co-Authored-By: Claude Sonnet 4.6 <[email protected]>
2026-04-04 20:44:38 -05:00
osobhandClaude Sonnet 4.6 1c107fe58a Apply rustfmt to entire workspace
Runs cargo fmt --all; all 573 tests still passing, clippy still clean.
No logic changes — formatting only.

Co-Authored-By: Claude Sonnet 4.6 <[email protected]>
2026-04-04 20:31:33 -05:00
osobhandClaude Sonnet 4.6 3d524e2d63 Fix intra-doc link warnings; add clawsync-fs README and metadata
Doc fixes (20 warnings → 1 benign name-collision warning):
- clawsync-transport/quic.rs: QuicConfig::with_cert doesn't exist → backtick
- clawsync-onion/iblt.rs: bare `insert` link → backtick
- clawsync-core/lib.rs: simd_cdc is feature-gated → backtick
- clawhdf5-onion/annotation.rs: RevisionEntry/BranchEntry are in external
  clawhdf5-format crate, not re-exported → backtick
- clawhdf5-onion/gc.rs: compact_dead_epoch_revisions is private; flush links
  broken → backtick
- clawhdf5-onion/provenance.rs: RevisionEntry from external crate → backtick
- clawhdf5-onion/reader.rs: reconstruct_revision/revision_pages → Self:: prefix
- clawhdf5-onion/writer.rs: REV_FLAG_SNAPSHOT → crate::format:: path;
  reconstruct_revision → Self:: prefix
Remaining warning is `format` module/macro name collision — not a broken link.

clawsync-fs crate metadata:
- Add readme, keywords, categories to Cargo.toml
- Write README.md (CDC protocol diagram, module overview, usage examples)

Co-Authored-By: Claude Sonnet 4.6 <[email protected]>
2026-04-04 20:29:28 -05:00
osobhandClaude Sonnet 4.6 260e15f5b6 Initial commit: ClawSync v0.1.0
8-crate pure-Rust workspace for revision-aware HDF5 sync.

## Crates
- clawhdf5-onion: ClawOnion VFD — page-level versioned HDF5 storage,
  binary format, writer/reader, branch DAG, GC, snapshots, provenance
- clawsync-core: BLAKE3, xxHash3, FastCDC (+ SIMD NEON), zstd/lz4
- clawsync-onion: IBLT sketch, Merkle tree differ, packet differ/merger,
  ClawSyncManifest, SyncSelector
- clawsync-hdf5: dataset-level manifest, differ, patcher, wire payload
  reconstruction (apply_received_payloads)
- clawsync-transport: TCP, QUIC (quinn 0.11/TLS 1.3), SyncPeer abstraction,
  length-prefixed rkyv wire protocol (21 SyncMessage variants)
- clawsync-agent: OnionMemory, SyncScheduler, TcpSyncBackend,
  PeerCapabilities negotiation
- clawsync-fs: CDC-based delta sync for any file type; FsSyncClient/Server,
  W=16 pipelining, atomic writes
- clawsync-cli: push/pull/serve/hdf5-sync/serve-hdf5/sync/serve-fs +
  all local management commands; --quic on all network commands

## Key features
- IBLT pre-flight: O(revision count) vs rsync's O(file size)
- W=16 sliding-window push: 13–15x speedup over stop-and-wait at WAN RTT
- Dataset-granular HDF5 sync: only modified datasets transferred
- CDC delta for any file type: insertion-stable chunk boundaries
- Full revision DAG: branch, merge, rollback, export, snapshot, GC
- QUIC transport: TLS 1.3, per-message streams via quinn 0.11

## Tests
~573 passing (default features); ~589 with --features simd-cdc

## Performance (Apple Silicon)
- Reconstruct rev=100: 68 µs (target ≤ 1 ms)
- BLAKE3 Rayon 1 MB: 10.3 GiB/s (target ≥ 5 GB/s)
- GC 500 revisions: 20.6 µs (target ≤ 2 s)
- W=16 vs W=1 at 5 ms RTT: 14.8x speedup
- No-op pre-flight at 16 MB: 4 ms vs rsync 35 ms (7.8x)

Co-Authored-By: Claude Sonnet 4.6 <[email protected]>
2026-04-04 18:41:22 -05:00