Repository navigation
Handover asks live in the database, so a restart doesn't lose one (GRYT-2023) - #364
Merged
Merged
Conversation
…YT-2023) pendingAsks was an in-memory Map. Restarting a server for 1.12.7 dropped the handover Sivert's Mac had asked for on pp.sivert.io, with its device name, and the device holding the key never heard about it again. Asks now go in a dm_key_asks table: one row per account and asking key, with the device name and when it first asked. They're named by the asking binding instead of a socket id, which a restart also throws away. That name still goes out as askerId, so older clients keep working. Approving, saying no or stopping the reset removes the row, and so does expiry after 30 days. A no goes to every device on the account, with the binding, and only the device that asked acts on it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This was referenced Nov 3, 2026
The merge test checks every column that can hold a server user id. A guest's asks were for the guest's own key, so they're deleted like its push devices, and the device asks again as the account. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
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.
When pp.sivert.io restarted for 1.12.7, it lost the handover your Mac had asked for.
pendingAsksindmKeys.tswas a Map in memory. The 30-day clock survived because it sits inusers, but the request itself, the asking device's name and the prompt on the device with the key did not.What changes
dm_key_asks (server_user_id, binding, device_name, created_at). Asking again keeps the firstcreated_at. Five per account at most, and rows older than 30 days are deleted when the table is read.askerId, so released clients send it straight back on deny.dm:key:handover:pendingreplays from the table. The asking device gets its own ask back and ignores it, because both apps only show an ask on a device whose key matches the current one.dm:key:handover:denied { binding }to the whole account, since there's no socket to aim at after a restart. The client PR makes only the asking device act on it.ok: falsebefore telling anyone. It used to notify the other devices first, for an ask there was nothing to hand over for.dm:key:reset:cancel("that wasn't me") also removes the ask, so the prompt doesn't come back.Look at
connection.tsand the cap query indmKeyAsks.ts.denied, so if two of your devices are both asking and one gets a no, both show it until the client PR ships.Still open, not in this PR: an ask with a different binding replaces the reset and restarts its clock. Somebody with your password could keep a lost-device reset from ever finishing by asking from a fresh key every few weeks. That's the reset design from GRYT-1886, not this table, so it's its own task.
Tests: the three handover tests now ask on an account that has a key, and a new one checks that approving and "that wasn't me" both remove the row. All 20 pass.
🤖 Generated with Claude Code