Repository navigation
Send message history when linking a device (GRYT-1574) - #33
Merged
Merged
Conversation
Build item 9 in docs/pairing-design.md. When the app passes its archive, the approving device (A) sends its history to the new one (N). On Approve, A notes each MLS group's position, then reads the archive newest day first through HistoryArchive, seals it into chunks with @gryt/crypto's chunk format and uploads them to the relay. The envelope's history carries the key and the manifest of whatever is up after at most five seconds. Later sealed "history" messages list the rest, a page of 180 entries at a time, each with its relay slot. After the adds, A sends the tail. That's every message it archived past the snapshot that N can't read: before N's add, or sent in an older epoch and landing after it. The app reports those with noteMessage. A waits a minute for late ones, sends a last message marked final, and leaves the session open, because closing it deletes the chunks. N fetches chunks newest first, checks each one against its manifest entry, and hands each message to HistorySink once. A chunk that fails the check is refused and counted. A chunk the relay no longer has is counted as missing. N closes the session once the final message has come and every chunk is handled. The relay has no chunk endpoints yet (GRYT-1591), so the client and the fake follow the design: PUT, GET and DELETE on /sessions/:id/chunks/:n, with the sealed chunk as base64url in JSON. Co-Authored-By: Claude Opus 5.5 <[email protected]>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
GRYT-1574. Build item 9 in
docs/pairing-design.mdon crypto main. It builds on #28'saddOwnDeviceandgroupPositionsand #29's pairing client.What happens now
A (approving):
groupPositions, then walks the archive throughHistoryArchive. That's per conversation, a page at a time, merged newest UTC day first across servers.planHistoryChunks,sealHistoryChunk, and a PUT to the relay. A chunk only gets listed once it's uploaded.historycarries the key and the manifest of what's up after at most 5 seconds (or 10 seconds before the approval deadline). Anything after that goes in sealed{t: "history", chunks: [{n, ...entry}], total, final}messages, 180 entries each.final.N (new device):
openHistoryChunkagainst each entry. A chunk that fails is refused, one the relay lost is missing, and both are counted. Neither stops the rest.HistorySinkonce, keyed by scope, conversation and message id.Both sides get
historyandsubscribeHistoryfor progress (messages, total, chunks, missing, refused, truncated, complete). Cancel works as before, at any point.API changes the apps will see
OwnDeviceAdderneedsgroupPositionsnow.MlsDmDriveralready has it, so passing the driver works.historyon both sides,lateWindowMson A.noteMessageon A. The app calls it for every MLS message it archives while a pairing runs, sent or received, with its seq and epoch. Without it the tail is empty.sendingon A, and new end reasonhistory_failedon N for when the sink throws.Relay
auth#45 has no chunk endpoints. The design has them as auth step 4. I built against the shape in the design, with a fake:
PUT/GET/DELETE /sessions/:id/chunks/:n, sealed bytes as base64url in{body}. I picked JSON over raw bytes because React Native's fetch is patchy with binary bodies. That's GRYT-1591 now.Limits
The relay allows 64 messages a session for both sides together. N uses four and the envelope one. So A lists at most 400 + 40 × 180 = 7,600 snapshot chunks, and stops at 248 MiB. Past either, the oldest stay behind and
truncatedsays so.Least sure about
ready.relay_error. It could link without history instead.linkedfor up to an hour, since A no longer closes the session. Both apps take the same core release, so this shouldn't come up.Not in this PR
Tests (
src/pairing/history.test.ts, fake relay and fake clock)cancelled_by_other.I checked the tail and ordering tests fail when the tail, the dedupe, the epoch check or the newest-first pick is broken.
Normal review: nothing here is in a review-required path.
🤖 Generated with Claude Code