XIP-64: Message transfer

Author: Naomi Plasterer (@nplasterer)

Abstract

The initial version of history sync introduced by XIP-31: Message History request system has worked well but is causing confusion for many integrators because of a lot of things happening automatically.

This version supercedes XIP-31 and:

  • Renames the history sync feature to history transfer

  • Renames the group sync feature to preference sync

  • Requires more explicit actions to make syncing more apparent

Specification

History transfer

History sync is now called history transfer.

History transfer will be enabled by default. Integrators who don’t want to share their message history with other installations can turn it off. By default, the history transfer server URL will be set to the Ephemera-hosted history server.

History transfer will require several function calls to successfully complete.

For example, given Installation A currently logged in with history and Installation B newly logged in with no history:

  1. Installation B must make a request for history by calling initateHistoryRequest(timeframe). This request can include a timeframe so an app can get the message history from the past year or longer. All consent records will always be included.

  2. Installation A would have a list of requests for history visible by calling listHistoryRequests. This list would show which installation initiated the request as well as the requested timeframe. There is also an option to streamHistoryRequests so an app can show requests live whenever they come in from another device. In the background, when syncing the history requests, a job is initiated to add the new installation to all existing conversations, bypassing the 30-minute window.

  3. Installation A would then call prepareHistoryUpload with the history request, which would return the size of the upload so an app can choose to display the upload time and give the user the option to cancel.

  4. Installation A would then call uploadHistory. This would initiate an upload to the history server URL with the latest prepared request. It would also send a message letting the sync group know the upload was successful and the upload location. It would return true when the upload is successful so the integrator can update the app UI. An app can check progress of the upload by calling uploadHistoryProgress which will return a number between 1 and 100, indicating the percentage complete.

  5. Installation B would then call listAvailableHistory to see a list of history available for download along with the size of the history. Note that history is stored on the server for only 24 hours before being deleted. There is also an option to streamAvailableHistory to get a live stream when the history becomes available.

  6. Installation B would then call downloadHistory which would initiate the download of the history to the local database and return true when the download is successful. An app can check progress of the upload by calling downloadHistoryProgress which will return a number between 1 and 100, indicating the percentage complete.

Preference sync

Group sync is now called preference sync.

  • A preference sync group is created on client creation regardless of whether a history transfer server URL is present.

  • To sync preferences between two or more installations, an app can call syncAllConversations or an explicit syncPreferences.

  • Local preferences that can be synced between multiple installations include HMAC keys and consent records.

Backward compatibility

Integrators who relied on the automatic nature of history transfer will now be required to implement specific UI patterns for users to be able to export and import history between installations.

Security considerations

Threat model

Allowing history transfer to be automatic and enabled by default created an attack vector where a malicious actor could create an installation and get message history without the user accepting the request for history.

Copyright

Copyright and related rights waived via CC0.

Can you expand on this part a bit? I’m not sure what the 30 minutes window is.

Is the intended UX for the user to see the transfer request on their device A, and explicitly approve it? I do see how this would help the user clear the current challenge of assuming history sync will magically happen when they sign in to device B. With your proposed UX the user signs in to device B, clicks some kind of button to “transfer history” and a message could be shown to prompt them to “open your other device and approve the transfer”. I think the biggest problem now is that the user doesn’t know they need to open their existing app to enable the sync.

Is there an ability for device B to list the existing inboxes in which the history transfer request can be approved? Like, “approve your transfer request on device 1, device 2 or device 3”

Yes I think we may implement a flow that we had previously mocked that would require you to enter a pin on another installation. So when you trigger the request it will give you a 4 digit code to enter on the other device. This would atleast give a call to action to open the other installation.

So it would be based on installations so yes. You could list out all the installations that the user has it’s public information on the InboxState. The installation only shows the createdAt date though… so it’s not as easy as saying “Approve on your iPhone” but for privacy reasons that’s a good thing. It would be more like
“You can approve this request from 5 other installations” and then you can list the installations and the date they were created.

I’m still a little fuzzy on this myself but sometimes when you login without transferring history it can take 30 minutes for your old conversations to show up again. This is due to a function we call called maybe_update_installations
this is used to limit the amount of time a client does the heavy process of searching for and then adding any new installations that may be missing in a group. So if you just looked for new installations it will wait 30 minutes before looking again.