Files
tutabridge/SDK_PRS.md
T
Anthony d0457b24f6 Track sdk-mail-set-entry-id in the SDK integration
New SDK branch off upstream/master that adds the
`mail_set_entry_id::{construct, deconstruct}` helpers. Cherry-picked into
`tutabridge-integration` so the bridge can decode `MailSetEntry` ids
straight from event-bus payloads in the upcoming delta-apply path —
no REST round-trip when a mail moves between two cached folders.

Held from upstream submission until a working bridge consumer ships.
2026-05-28 14:26:30 +02:00

6.4 KiB

SDK changes tracking

TutaBridge depends on a few changes to the Tuta Rust SDK (tuta-sdk/rust/sdk, vendored as the tuta-repo submodule). To stay able to switch back to Tuta's upstream at any time, every SDK change is kept as its own single-commit branch off upstream/master, each independently reviewable / mergeable by Tuta. They are combined only in the tutabridge-integration branch, which is what the submodule actually checks out.

  • Fork (our branches live here): spartanz51/tutanota
  • Upstream: tutao/tutanota
  • Integration branch (sum of the changes below): tutabridge-integration

Rule: never accumulate unrelated SDK changes on one branch. One concern = one branch = one commit, rebasable on upstream/master.

Branches

Branch Summary Upstream PR Fork PR Submitted to upstream Merged Live-tested
sdk-load-multiple EntityClient/CryptoEntityClient.load_multiple (batch entity loading) tutao#10854 yes (open) no yes (sync 500 mails)
sdk-blob-element-reading BlobFacade.load_blob_element + MailFacade.load_mail_details_blob (read MailDetailsBlob) tutao#10870 yes (open) no yes (body decrypt over IMAP)
sdk-2fa-session Interactive 2FA: initiate_session, authenticate_with_second_factor_totp, is_second_factor_pending, cancel_create_session tutao#10871 yes (open) no yes (full TOTP login)
sdk-folder-system Rebuild FolderSystem tree (system/custom/nested), add MailSetKind Label/Imported/Scheduled + accessors spartanz51#4 no (held) no yes (custom folders listed + read over IMAP)
sdk-move-mails MailFacade.move_mails (move to an arbitrary folder via MoveMailService) spartanz51#5 no (held) no yes (IMAP MOVE between folders)
sdk-event-bus WebSocket EventBusClient (/event?…) — realtime entity updates with catch-up via groupsToLastEventBatchIds, plus observable WsState no (held) no yes (live-tested over Phase 2/3 bridge integration, 26 unit tests)
sdk-mail-set-entry-id mail_set_entry_id::{construct, deconstruct} — encode/decode MailSetEntry._id (4-byte truncated timestamp + 9-byte raw Mail id, base64url-no-pad) no (held) no will be (consumed by the bridge realtime delta optimisation; 8 unit tests, TS test vector asserted)

Notes per branch

sdk-load-multiple

Additive utility, mirrors TS EntityClient.loadMultiple. Maintainer (charlag) asked why it's submitted (not user-facing) and about LLM use; answered honestly.

sdk-blob-element-reading

Additive. Mirrors TS blob reading + doBlobRequestWithRetry/tryServers. Returns MailDetails from load_mail_details_blob (matches TS).

sdk-2fa-session

Refactors create_session to delegate to initiate_session; reuses the existing parse_session_id; no clientIdentifier change. Additive otherwise.

sdk-folder-system

Held — not submitted upstream. It modifies the existing FolderSystem struct, which upstream marks as WIP (// this structure should probably change rather soon), so they likely want to design it themselves. Faithful port of FolderSystem.ts. Submit only if the other PRs get traction and a maintainer signals appetite — align the API with them first. Needed locally regardless for custom/nested folder support in the bridge. Live-tested in the bridge: custom folders are listed and read over IMAP (the custom-folders bridge change keys everything by folder id).

sdk-event-bus

Held — not submitted upstream. Port of src/common/api/worker/EventBusClient.ts: WebSocket client for /event?…, reconnect/backoff matching the TS close-code semantics, catch-up of missed batches via the groupsToLastEventBatchIds query param. Entity-update batches are decoded from the server's untyped wire format into a small typed EntityUpdateBatch (the other message kinds stay as raw serde_json::Value since the bridge does not need them yet — consumers can apply the SDK's type machinery if they want a typed view). Exposes a WsState (Stopped/Connecting/Connected/Reconnecting) via state() -> watch::Receiver<_> so UIs can render the connection lifecycle live. New dependency: tokio-tungstenite configured to reuse the existing rustls stack; gated behind the existing net feature. 26 unit tests cover URL building, wire parsing, reconnect logic and state-broadcast behaviour. Live-tested as part of the bridge realtime sync (Phase 2/3).

sdk-mail-set-entry-id

Held — not submitted upstream. New module mail_set_entry_id exposing construct(receive_date, mail_id) -> CustomId and the inverse deconstruct(custom_id) -> Result<(DateTime, GeneratedId), _>. Mirrors the TypeScript helpers in src/platform-kit/meta/EntityUtils.ts — a MailSetEntry._id.element_id is a 13-byte buffer (4 bytes of timestamp shifted right by 10 bits, then 9 raw bytes of the referenced Mail.element_id) encoded as base64url-no-pad. Knowing the encoding lets a realtime consumer extract the mail id directly from a MailSetEntry CREATE/DELETE event without an extra REST round-trip. 8 unit tests assert the TS test vector verbatim plus round-trip and four error shapes. Submit upstream once a real SDK consumer (the bridge realtime delta path) ships using it.

Rebasing on a newer upstream

cd tuta-repo
git fetch upstream
# rebase each SDK branch on the new master (resolve only if upstream touched
# the same files — so far it hasn't)
git rebase upstream/master sdk-load-multiple
git rebase upstream/master sdk-blob-element-reading
git rebase upstream/master sdk-2fa-session
git rebase upstream/master sdk-folder-system
git rebase upstream/master sdk-move-mails
git rebase upstream/master sdk-event-bus
git rebase upstream/master sdk-mail-set-entry-id
# rebuild the integration branch from the rebased branches
git checkout -B tutabridge-integration upstream/master
git cherry-pick sdk-load-multiple sdk-blob-element-reading sdk-2fa-session sdk-folder-system sdk-move-mails sdk-event-bus sdk-mail-set-entry-id

When an upstream PR merges, drop that branch from the cherry-pick list — the integration branch shrinks until (ideally) it equals upstream/master.