Expand description
Daemon-held multi-device sync + execution-lease subsystem — the sync.* /
lease.* WS surface’s engine (slice B6 of
docs/proposals/multi-device-sync.md).
One SyncSubsystem per daemon is one device in the user’s sync fleet:
it owns a car_sync::SyncSession (the pump over an append-only oplog +
deterministic fold) against a car_sync::FsRelay rooted at
<journal_dir>/sync/relay/ — so the single-user two-device case (two Macs
sharing that directory, e.g. via a synced folder, or two daemons on one host
in tests) converges out of the box — plus an in-process linearizable
car_sync::InMemoryLeaseCoordinator for the execution lease.
The handler layer (handler.rs) is thin: it parses params and calls the
&mut self methods here under the subsystem’s tokio::sync::Mutex, which is
why the convergence + fence + lease behaviour is unit-tested directly on
SyncSubsystem (two instances sharing an FsRelay dir + a cloned
coordinator) rather than only through the WS round-trip.
§State domains: wired vs. pending (honest boundary)
- Conversation — wired end-to-end.
SyncSubsystem::record_turnroutes a conversation write through the oplog (aSurface::Conversationop), andSyncSubsystem::resumereturns the repaired, provider-validVec<Message>fromcar_sync::SyncState::resume_messages— so transcript resume across devices is real, not a stub. What is not done: auto-teeing the daemon’s existing internal conversation persistence (car-inference/memgine) into the oplog — a host usessync.record_turnexplicitly. That internal reroute is the pending B2 adoption step. - Intent ledger — wired.
SyncSubsystem::record_intentwrites the leased-executionSurface::Intentledger (terminal-guarded), andSyncSubsystem::fence_checkruns the B6 dispatch fence over it. - Any other surface — a generic tee.
SyncSubsystem::appendrecords an op on anycar_sync::Surface(knowledge/skill/declagent/routing/…), so a host can tee those domains into the oplog today. Rerouting the daemon’s own knowledge/registry write paths through it is the pending step.
§Encryption & distributed coordination
Two subsystem flavors:
SyncSubsystem::open— the local default: a shared-directoryFsRelay+ an in-processInMemoryLeaseCoordinator, cleartext payloads. The single-host / synced-folder case.SyncSubsystem::open_remote— the Parslee-backed path (selected when.car/config.toml[sync] backend = "parslee"): aNetworkRelay+ distributedNetworkLeaseCoordinatorover acar_sync::SyncTransport(the realcar_parslee::ParsleeSyncTransport, or aLoopbackTransportreference server in tests), scoped to the user’s Parslee identity, with op payloads E2E-encrypted under a login-derivedSyncKeyProvider. The session encrypts-on-append / decrypts-before-fold, so the relay holds only ciphertext, and the lease is a genuinely cross-device fencing register. This is “phone + Mac after one login” and it is exercised end-to-end (two_remote_devices_converge_e2e_through_the_network_relay).
The cross-device key is login-derived: car_sync::DerivedKeyProvider
from_passphrase is the zero-knowledge source that works today (same
passphrase → same keys on every device, the server never sees it); a
Parslee-issued per-user master is the alternative. Config propagation has
a tested tee primitive (SyncSubsystem::tee_config/SyncSubsystem::config_get,
partition-guarded). Under E2E, checkpoint publishing is guarded off
(SyncSession::publish_checkpoint) so no cleartext/inconsistent snapshot
reaches the relay.
Remaining follow-ups: the live Parslee server implementing the contract
(cross-repo — docs/proposals/parslee-sync-backend.md); per-subsystem
adoption of the config tee (each config write-path calling tee_config
- applying
config_geton pull); and per-scope encrypted checkpoint push (restores relay-side GC — until then the server owns retention).
Structs§
- Host
Endpoint - One device’s announced A2A endpoint and peer identity.
- Sync
Subsystem - A daemon device’s sync endpoint + lease coordinator. Held behind a
tokio::sync::MutexonServerState; every method is&mut self.
Functions§
- parse_
intent_ status - Parse an
IntentStatusstring. - parse_
scope - Parse an optional
scopeparam:{scope: "personal"}(default) or{scope: {org: "acme"}}/{org: "acme"}→Shared. - parse_
surface - Parse a
surfaceparam string into aSurface.registry:<kind>maps toRegistry { kind }. Unknown surfaces error (never silently defaulted).