Feeds the encryption-relevant slice of a /sync response into the
crypto machine -- design doc section 7. This is how the machine learns
which devices exist: a product that never calls this encrypts to
nobody.
Accepted shape.syncDelta must be a plain object using exactly
matrix-sdk-crypto's own snake_case field names below, every one
optional and defaulting independently when absent:
{ to_device_events?: object[] // raw to-device events, as received changed_devices?: { changed:string[]; left: string[] } one_time_keys_counts?: Record<string, number> unused_fallback_keys?: string[] next_batch_token?: string }
This is not a /sync response, and a /sync response is rejected.
It is the encryption-relevant slice of one, under matrix-sdk-crypto's
field names, and the two sets of names have no member in common: a real
/sync body's top-level keys are next_batch, rooms, presence,
account_data, to_device, device_lists,
device_one_time_keys_count and device_unused_fallback_key_types,
none of which is one of the five above. So passing the response verbatim
throws malformed_payload before native is called -- deliberately and
loudly, because the alternative was a call that resolves and teaches the
machine nothing.
An earlier version of this paragraph said the whole response could be
handed over verbatim. That was false, and the guard eleven lines above
proved it false; it was corrected by the level 2 interoperability test,
which is the first thing that ever fed this function a payload a real
homeserver produced.
Five fields must be renamed, and nothing else forwarded:
in a /sync response
in syncDelta
to_device.events
to_device_events
device_lists
changed_devices
device_one_time_keys_count
one_time_keys_counts
device_unused_fallback_key_types
unused_fallback_keys
next_batch
next_batch_token
Omit a field the response does not carry rather than passing
undefined; each defaults independently. Everything else the response
holds -- rooms, presence, account_data -- is no part of this
payload.
Use encryptionSlice to build syncDelta from a /sync response
rather than writing this mapping again -- it is this same rename table,
as code:
{} is the shape an ordinary, uneventful sync sends, and is accepted:
it reports nothing, correctly. camelCase silently does nothing, and
this is the one call where that matters most -- every field above
defaults independently and unknown keys are ignored, so
{ toDeviceEvents: [...] } parses into an entirely-default payload,
resolves successfully, and teaches the machine nothing, indistinguishable
from {} on the caller's side (the return type is frozen void). A
non-empty payload naming none of the five fields above -- the shape a
camelCase mistake, or any other wrong shape, produces -- is rejected
with malformed_payload before native is ever called. A payload naming
at least one recognised field alongside others this library does not
consume (a homeserver-added /sync field, for instance) is accepted,
and the extra field is ignored -- tolerance for exactly that case is why
this guard checks for some recognised field rather than rejecting any
unrecognised one.
Returns void, not the native call's own to-device/session counts: that
return type is frozen from M1a. A product that needs those counts reads
them off the sync response it already holds.
Feeds the encryption-relevant slice of a
/syncresponse into the crypto machine -- design doc section 7. This is how the machine learns which devices exist: a product that never calls this encrypts to nobody.Accepted shape.
syncDeltamust be a plain object using exactlymatrix-sdk-crypto's own snake_case field names below, every one optional and defaulting independently when absent:This is not a
/syncresponse, and a/syncresponse is rejected. It is the encryption-relevant slice of one, undermatrix-sdk-crypto's field names, and the two sets of names have no member in common: a real/syncbody's top-level keys arenext_batch,rooms,presence,account_data,to_device,device_lists,device_one_time_keys_countanddevice_unused_fallback_key_types, none of which is one of the five above. So passing the response verbatim throwsmalformed_payloadbefore native is called -- deliberately and loudly, because the alternative was a call that resolves and teaches the machine nothing.An earlier version of this paragraph said the whole response could be handed over verbatim. That was false, and the guard eleven lines above proved it false; it was corrected by the level 2 interoperability test, which is the first thing that ever fed this function a payload a real homeserver produced.
Five fields must be renamed, and nothing else forwarded:
/syncresponsesyncDeltato_device.eventsto_device_eventsdevice_listschanged_devicesdevice_one_time_keys_countone_time_keys_countsdevice_unused_fallback_key_typesunused_fallback_keysnext_batchnext_batch_tokenOmit a field the response does not carry rather than passing
undefined; each defaults independently. Everything else the response holds --rooms,presence,account_data-- is no part of this payload.Use encryptionSlice to build
syncDeltafrom a/syncresponse rather than writing this mapping again -- it is this same rename table, as code:{}is the shape an ordinary, uneventful sync sends, and is accepted: it reports nothing, correctly. camelCase silently does nothing, and this is the one call where that matters most -- every field above defaults independently and unknown keys are ignored, so{ toDeviceEvents: [...] }parses into an entirely-default payload, resolves successfully, and teaches the machine nothing, indistinguishable from{}on the caller's side (the return type is frozenvoid). A non-empty payload naming none of the five fields above -- the shape a camelCase mistake, or any other wrong shape, produces -- is rejected withmalformed_payloadbefore native is ever called. A payload naming at least one recognised field alongside others this library does not consume (a homeserver-added/syncfield, for instance) is accepted, and the extra field is ignored -- tolerance for exactly that case is why this guard checks for some recognised field rather than rejecting any unrecognised one.Returns
void, not the native call's own to-device/session counts: that return type is frozen from M1a. A product that needs those counts reads them off the sync response it already holds.