pub struct ShippedEmbedding {
pub memory_id: String,
pub model: String,
pub dim: usize,
pub vector: Vec<f32>,
}Expand description
#1566 / #1579 B1 — embed-once-replicate-vector. A source-side
embedding shipped alongside its memory row in the federation
/sync/push payload (wire key crate::models::field_names::EMBEDDINGS).
§Wire contract
-
The array rides INSIDE the JSON body that
sync::post_onceserialises once and signs (X-Memory-Sigover the exact body bytes, nonce-bound per #922), so the vector’s TRANSIT integrity is covered by the same Ed25519 signature + replay protection as the memory rows themselves: a vector altered IN FLIGHT invalidates the signature.Trust boundary (#1584). The signature attests the SENDER and that the bytes were not altered in transit — it does NOT attest that the f32 values are a well-formed embedding, nor that the vector honestly embeds the shipped
(title, content). The content↔vector honesty is an inherent limit of shipping sender-computed vectors (the receiver trusts the enrolled peer not to mislabel). The VALUE DOMAIN, however, is receiver-enforced:sanitize_shipped_vectorrejects non-finite components and L2-normalizes the rest before storage, so a peer cannot poison cosine ranking with a NaN/±Inf or high-magnitude vector. (Non-finite components additionally cannot cross the JSON wire at all — serde serialises them tonulland the strictVec<f32>decoder rejects it with400.) -
Decode is TOLERANT of absence: the receiver’s
SyncPushBodyfield defaults to an empty vec, so pushes from older peers (noembeddingskey) and pushes to older peers (unknown fields are ignored — request structs are deliberately permissive per #1052) both interoperate. The fleet swaps as one, but the protocol must not hard-require the field.
§Receive contract
The receiver stores vector directly ONLY when dim matches its
own configured embedder dimensionality (the same dim-safety
property recall’s H7 CosineComparison::DimensionMismatch exists
for). On mismatch — or when no vector was shipped — the row falls
back to the deferred background-embed path; either way the
receiver acks after commit WITHOUT a synchronous embed (~1s/row
via ollama pre-#1566, which rode inside the sender’s quorum-ack
window and drove the deadline_exceeded → DLQ cascade).
Fields§
§memory_id: StringId of the memory row (in the same push) this vector belongs to.
model: StringHuman-readable id of the model that produced the vector
(sender’s Embedder::model_description()). Observability only —
the dim gate is the load-bearing safety check.
dim: usizeDimensionality the sender claims for vector. Receivers verify
dim == vector.len() AND dim == local embedder dim before
storing the vector directly.
vector: Vec<f32>The embedding vector itself.
Implementations§
Trait Implementations§
Source§impl Clone for ShippedEmbedding
impl Clone for ShippedEmbedding
Source§fn clone(&self) -> ShippedEmbedding
fn clone(&self) -> ShippedEmbedding
1.0.0 (const: unstable) · Source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
source. Read moreSource§impl Debug for ShippedEmbedding
impl Debug for ShippedEmbedding
Source§impl<'de> Deserialize<'de> for ShippedEmbedding
impl<'de> Deserialize<'de> for ShippedEmbedding
Source§fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>where
__D: Deserializer<'de>,
fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>where
__D: Deserializer<'de>,
Auto Trait Implementations§
impl Freeze for ShippedEmbedding
impl RefUnwindSafe for ShippedEmbedding
impl Send for ShippedEmbedding
impl Sync for ShippedEmbedding
impl Unpin for ShippedEmbedding
impl UnsafeUnpin for ShippedEmbedding
impl UnwindSafe for ShippedEmbedding
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> DeserializeOwned for Twhere
T: for<'de> Deserialize<'de>,
impl<T> ErasedDestructor for Twhere
T: 'static,
Source§impl<T> Instrument for T
impl<T> Instrument for T
Source§fn instrument(self, span: Span) -> Instrumented<Self>
fn instrument(self, span: Span) -> Instrumented<Self>
Source§fn in_current_span(self) -> Instrumented<Self>
fn in_current_span(self) -> Instrumented<Self>
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self>
fn into_either(self, into_left: bool) -> Either<Self, Self>
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 moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
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