Skip to main content

SyncSubsystem

Struct SyncSubsystem 

Source
pub struct SyncSubsystem { /* private fields */ }
Expand description

A daemon device’s sync endpoint + lease coordinator. Held behind a tokio::sync::Mutex on ServerState; every method is &mut self.

Implementations§

Source§

impl SyncSubsystem

Source

pub fn open(root: &Path) -> Result<Self, String>

Open the daemon-default subsystem rooted at root (<journal_dir>/sync/): a persistent per-device id at root/device-id, this device’s oplog + checkpoints under root/<device_id>/, and a shared FsRelay at root/relay/. Uses the real system wall clock and a fresh in-process lease coordinator.

Source

pub fn open_with( device_id: String, device_dir: &Path, relay_dir: &Path, coordinator: Box<dyn LeaseCoordinator + Send>, wall: WallClock, ) -> Result<Self, String>

Open with explicit paths, coordinator, and clock — the injection point the tests use to run two devices (distinct device_dirs, one shared relay_dir, a cloned coordinator register).

Source

pub fn open_remote( root: &Path, transport: Arc<dyn SyncTransport>, scope: impl Into<String>, key_provider: Arc<dyn SyncKeyProvider>, ) -> Result<Self, String>

Open a remote (Parslee-backed) subsystem. This device’s oplog + checkpoints stay local under root/<device_id>/, but the relay and lease register are the network transport (e.g. ParsleeSyncTransport, or a LoopbackTransport in tests), scoped to scope — the user’s Parslee identity (user:<id> / org:<id>) — so every device on that login converges through one service. Op payloads are E2E-encrypted under key_provider (login-derived), so the relay only ever holds ciphertext. The daemon selects this over SyncSubsystem::open when .car/config.toml [sync] backend = "parslee".

Source

pub fn device_id(&self) -> &str

Source

pub fn status(&mut self) -> Result<Value, String>

sync.status — the roster, this device’s journal frontier (per-device max seq), the relay’s stable frontier, and the divergence-invariant state hash.

Source

pub fn append( &mut self, scope: Scope, surface: Surface, payload: Value, ) -> Result<Value, String>

sync.append — record an op on any surface (the generic domain tee).

Source

pub fn tee_config( &mut self, domain: &str, value: Value, ) -> Result<Value, String>

Replicate a portable config domain onto the oplog so every device on this login converges it (LWW per domain) — how a setting changed on the Mac reaches the phone. The tee primitive: the daemon’s own config write-paths (agent-permissions, messaging allowlist, …) call this after a local write; that per-subsystem adoption is the remaining wiring. It refuses a device-local domain (car_sync::partition) — the guard that keeps a secret or an OS grant off the relay; value must already exclude any device-local sub-field (e.g. a keychain ref stays a per-device pointer). Safer than raw sync.append (which any surface can use).

Source

pub fn config_get(&self, domain: &str) -> Value

The converged (folded LWW) value of a config domain, or null if no device has teed it yet — the read side an adopting subsystem applies after a pull to reconcile a peer’s change onto this device.

Source

pub fn publish_host_endpoint( &mut self, name: &str, url: &str, pubkey: &str, ) -> Result<Value, String>

Announce this device’s peer-reachable A2A endpoint to the user’s other devices.

Idempotent by construction: the entry is keyed on this device’s id and folds LWW, so re-announcing on every start overwrites rather than accumulates. Call it whenever the A2A listener comes up — the address can change between runs (DHCP, a new --a2a-public-url), and a stale entry would send peers at an address nothing answers on.

Source

pub fn host_endpoints(&self) -> Vec<HostEndpoint>

Every other device’s announced endpoint.

This device is excluded: it is not its own peer, and listing it would put a self-addressed row in every peer listing.

The pubkey is what makes these peers reachable rather than merely visible. It arrived over the E2E-encrypted oplog, so only a device holding this login’s key material could have published it — which is exactly the property that lets this host trust it without an operator comparing fingerprints by hand.

Source

pub fn knowledge(&self) -> Vec<Value>

The converged (folded) knowledge facts — the read side of the assistant’s synced memory. Returns each fact’s {subject, body} payload in ASCENDING (hlc, op_id) order (as log_entries yields them), so a reducer that keeps the LAST occurrence per subject gets the newest value. The assistant re-ingests these after a pull so a fact learned on one device surfaces in recall on another. Raw (unreduced) on purpose — the caller reduces newest-per-subject so the ordering contract stays in one place.

Source

pub fn assistant_checkpoint_put( &mut self, checkpoint: AssistantCheckpoint, ) -> Result<Value, String>

Persist the exact model-facing supervised-assistant checkpoint in the existing append-only oplog. LWW is per session id, while revision prevents a delayed writer from replacing a newer local checkpoint.

Source

pub fn assistant_checkpoint_get( &self, session_id: &str, ) -> Result<Option<AssistantCheckpoint>, String>

Load the latest exact checkpoint for one supervised session.

Source

pub fn assistant_action_put( &mut self, record: SupervisedActionRecord, ) -> Result<Value, String>

Append one monotone supervised-action lifecycle record. This ledger is separate from scheduled-run Intent because approval and indeterminate dispatch are distinct safety states, not aliases for pending/failed.

Source

pub fn assistant_action_get( &self, action_id: &str, ) -> Result<Option<SupervisedActionRecord>, String>

Source

pub fn record_turn( &mut self, scope: Scope, conversation_id: &str, role: &str, content: &str, tool_calls: Vec<Value>, tool_use_id: Option<&str>, timestamp: u64, ) -> Result<Value, String>

sync.record_turn — the Conversation domain, routed through the oplog so sync.resume is real. roleuser|assistant|tool.

Source

pub fn record_intent( &mut self, scope: Scope, intent: &Intent, ) -> Result<Value, String>

sync.record_intent — write a leased-execution intent to the Surface::Intent ledger (terminal-guarded: a pending/failed write for an already-committed run is a no-op). This is what populates the committed-run oracle the dispatch fence reads.

Source

pub fn pump(&mut self) -> Result<Value, String>

sync.pump — one reconciliation round (push journal-durable own ops → pull → verify → fold → ack). This drives push/pull/ack against the relay.

Source

pub fn checkpoint(&mut self) -> Result<Value, String>

sync.checkpoint — compute + publish a device-side checkpoint at the relay’s stable frontier (the E2E-ready snapshot; the relay never folds).

Source

pub fn rebase(&mut self) -> Result<Value, String>

sync.rebase — cold bootstrap / straggler re-entry: re-anchor on the relay’s latest checkpoint (carrying uncovered local ops across).

Source

pub fn transcript(&self, conversation_id: &str) -> Value

sync.transcript — the ordered, role-threaded raw transcript projection.

Source

pub fn resume(&self, conversation_id: &str) -> Result<Value, String>

sync.resume — the repaired, provider-valid Vec<Message> a host replays to continue the conversation (the verbatim resume path).

Source

pub fn fence_check( &mut self, agent_id: &str, run_id: &str, epoch: u64, ) -> Result<Value, String>

sync.fence_check — the B6 executor dispatch fence at the point of effect: the durable committed-run oracle read + the linearizable “am I still epoch N?” read. Only may_dispatch == true authorizes the effect.

Source

pub fn lease_acquire( &mut self, agent_id: &str, ttl_ms: u64, ) -> Result<Value, String>

lease.acquire — CAS-acquire the per-agent execution lease (this device is the holder); on grant the monotone fencing epoch bumps.

Source

pub fn lease_renew( &mut self, agent_id: &str, epoch: u64, ttl_ms: u64, ) -> Result<Value, String>

lease.renew — heartbeat the lease (no epoch bump), iff still the holder.

Source

pub fn lease_release( &mut self, agent_id: &str, epoch: u64, ) -> Result<Value, String>

lease.release — clean handoff (next acquire skips the TTL wait).

Source

pub fn lease_status(&mut self, agent_id: &str) -> Result<Value, String>

lease.status — the linearizable read of the current lease (or null).

Trait Implementations§

Source§

impl Debug for SyncSubsystem

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<ST, DT> CastableFrom<ST, Initialized, Initialized> for DT
where ST: ?Sized, DT: ?Sized,

Source§

impl<ST, DT> CastableFrom<ST, Uninit, Uninit> for DT
where ST: ?Sized, DT: ?Sized,

Source§

impl<S, T> Duplex<S> for T
where T: FromSample<S> + ToSample<S>,

Source§

impl<T> ErasedDestructor for T
where T: 'static,

Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<S> FromSample<S> for S

Source§

fn from_sample_(s: S) -> S

Source§

impl<T> Instrument for T

Source§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
Source§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> IntoEither for T

Source§

fn into_either(self, into_left: bool) -> Either<Self, Self>

Converts self into a Left variant of Either<Self, Self> if into_left is true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
where F: FnOnce(&Self) -> bool,

Converts self into a Left variant of Either<Self, Self> if into_left(&self) returns true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

impl<F, T> IntoSample<T> for F
where T: FromSample<F>,

Source§

fn into_sample(self) -> T

Source§

impl<T> Pointable for T

Source§

const ALIGN: usize

The alignment of pointer.
Source§

type Init = T

The type for initializers.
Source§

unsafe fn init(init: <T as Pointable>::Init) -> usize

Initializes a with the given initializer. Read more
Source§

unsafe fn deref<'a>(ptr: usize) -> &'a T

Dereferences the given pointer. Read more
Source§

unsafe fn deref_mut<'a>(ptr: usize) -> &'a mut T

Mutably dereferences the given pointer. Read more
Source§

unsafe fn drop(ptr: usize)

Drops the object pointed to by the given pointer. Read more
Source§

impl<T> PolicyExt for T
where T: ?Sized,

Source§

fn and<P, B, E>(self, other: P) -> And<T, P>
where T: Sized + Policy<B, E>, P: Policy<B, E>,

Create a new Policy that returns Action::Follow only if self and other return Action::Follow. Read more
Source§

fn or<P, B, E>(self, other: P) -> Or<T, P>
where T: Sized + Policy<B, E>, P: Policy<B, E>,

Create a new Policy that returns Action::Follow if either self or other returns Action::Follow. Read more
Source§

impl<T> Read<Exclusive, BecauseExclusive> for T
where T: ?Sized,

Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
Source§

impl<T, U> ToSample<U> for T
where U: FromSample<T>,

Source§

fn to_sample_(self) -> U

Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = !

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, !>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<V, T> VZip<V> for T
where V: MultiLane<T>,

Source§

fn vzip(self) -> V

Source§

impl<T> WithSubscriber for T

Source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more