Skip to content

Tables for the MLS delivery service (GRYT-1500) - #240

Merged
sivert-io merged 1 commit into
mainfrom
claude/GRYT-1500-mls-ds-tables
Sep 25, 2026
Merged

sivert-io merged 1 commit into
mainfrom
claude/GRYT-1500-mls-ds-tables

Conversation

@sivert-io

@sivert-io sivert-io commented Sep 25, 2026 •

Copy link
Copy Markdown
Member

What to look at

  • appendMlsCommit in src/db/sqlite/mls.ts. It's the only place commit
    ordering is decided: read the group's epoch, compare, write, move it on,
    all inside BEGIN IMMEDIATE. The handlers in the next PR trust it.
  • recentDuplicate, the resend check, compares blobs against the last 100
    rows of a group's log. It's meant for a client retrying after a lost
    reply. I'm not sure a blob compare is how you'd want it done.
  • purgeOrphanedConversations now drops the MLS group as well. That's a
    change to an existing function.
  • mergeGuestIntoAccount moves MLS devices across. Where both identities
    have the same device id, the account's row is kept.

What's in it

Five tables for the MLS delivery service, stage 1 of
docs/mls-design.md:
devices (five per member), KeyPackages (20 per device plus a last-resort
one, each handed out once), groups (one per conversation, with the epoch and
the last seq), the log, and Welcomes waiting for their device. Every blob
is MLS wire bytes. The server never gets a key.

sweepMls is the retention sweep: log rows, Welcomes and handed-out
KeyPackage refs older than the cutoff, plus any group whose conversation is
gone. A group's epoch and head_seq never go back, so a cursor still means
the same thing after a sweep.

Nothing calls this yet. The handlers are in #241, which carries this commit
too so its CI can run. It's a draft until this one merges.

Tests

src/db/sqlite/mls.test.ts, 19 tests: the device cap, KeyPackages handed
out once and oldest first, the last-resort fallback, the first group per
conversation winning, one commit per epoch, resends, cursor paging,
Welcomes only deleted by their own device, retention, and the two lifecycle
changes. mergeGuest.test.ts's column audit caught the new columns, which
is how the merge change got written. Full suite: 1729 pass.

Task: GRYT-1500. Part of GRYT-754 and GRYT-1244.

🤖 Generated with Claude Code

Stage 1 of docs/mls-design.md in the crypto repo needs somewhere to keep
KeyPackages, Welcomes and each DM group's log. Five new tables, all holding
MLS bytes the server can't open plus what ordering and routing need:

- mls_devices: which devices a member has here, five at most.
- mls_key_packages: up to 20 per device plus one last-resort package.
  Handing one out clears its bytes but keeps the row, so a Welcome that
  names it by ref can still be routed. The retention sweep drops it later.
- mls_groups: one per conversation, with the current epoch and the last
  seq handed out. head_seq is kept here and not read off the log, because
  the log gets swept and a seq must never be handed out twice.
- mls_log: commits, proposals and application messages, in seq order.
- mls_welcomes: one row per receiving device, until that device acks it.

appendMlsCommit is where commits get ordered. In one IMMEDIATE transaction
it checks the commit's epoch against the group's, writes it and moves the
epoch on, or refuses and says what the epoch is now. The same bytes sent
again within the last 100 entries get the first seq back rather than a
second row, for a client retrying after a lost reply.

Two existing paths change. Purging an empty conversation drops its group
too: a DM id comes from the pair, so a group left behind would be handed to
the next DM those two open. And a guest merged into an account takes its
devices, KeyPackages and Welcomes along.

Nothing calls these yet. The socket handlers are in the next PR.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
@sivert-io
sivert-io merged commit 4342396 into main Sep 25, 2026
6 checks passed
@sivert-io
sivert-io deleted the claude/GRYT-1500-mls-ds-tables branch September 25, 2026 10:31
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant