Repository navigation
feat(sync): 10.3c pairing backfill — entities predating a pair now reach it - #468
Merged
Merged
Conversation
…ach it The ongoing producer (#467) fires on DEK install, so it only ever reaches entities created AFTER a device is paired. Everything written before the second device existed stayed stranded forever: the new device would sync new notes and never see a single old one. Either half alone leaves multi-device sync broken, which is why the rung named both. Runs on the IE-11 long-pass contract rather than a synchronous loop — this is O(entities x devices) HPKE seals fired by a pairing gesture, and blocking the main thread would freeze the UI at exactly the moment the user is watching a device pair. Yields every 25 entities, reports progress, honours an abort. Never throws, and that is deliberate: one entity that cannot be sealed must not strand every entity after it. A partial backfill is strictly better than an aborted one, and the next pairing event re-runs the pass. Counting is chosen so an offline run does not look like a broken one — a null fan-out (no relay, no siblings) and a placeholder refusal are both "nothing to do", not failures. Wired to onDevicesChanged, behind a single in-flight guard: the roster can change twice in quick succession and two concurrent passes over one vault would double the HPKE work for nothing. New repo method listIdsWithDek — the inverse of listMissingDekIds. Carries `type` because it is sealed into the wrap for cold materialisation, and fetching it per id would be a query per entity on a pass that is already O(entities x devices). SQL stays in the repo per convention. 8 tests on the pure pass. 1350 pass across sync/collab/storage/entities; typecheck and lint green. REMAINING on the rung: both declared gates. Co-Authored-By: Claude Opus 5 (1M context) <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.
The ongoing producer (#467) fires on DEK install, so it only ever reaches entities created after a device is paired. Everything written before the second device existed stayed stranded forever — the new device would sync new notes and never see a single old one. Either half alone leaves multi-device sync broken, which is why the rung named both.
Why it is a long pass, not a loop
This is O(entities × devices) HPKE seals fired by a pairing gesture. Blocking the main thread would freeze the UI at exactly the moment the user is watching a device pair. So it runs on the
IE-11contract: yields every 25 entities, reports progress, honours an abort signal.Deliberate failure semantics
nullfan-out (no relay, no siblings) and a placeholder refusal are both nothing to do, counted as skipped rather than failed.installEntityDekignores an equal ordinal, so re-running after a second pairing is safe and cheap.Wiring
Called from
onDevicesChanged, behind a single in-flight guard — the roster can change twice in quick succession, and two concurrent passes over one vault would double the HPKE work for nothing.New repo method
listIdsWithDek, the inverse oflistMissingDekIds. It carriestypebecause that is sealed into the wrap for cold materialisation (10.14), and fetching it per id would be a query per entity on a pass that is already O(entities × devices). SQL stays in the repo per convention.Verification
8 tests on the pure pass (zeroing on throw, continue-after-failure, abort, progress, offline-is-not-failure, multi-batch yield) · 1350 pass across sync / collab / storage / entities · typecheck + lint green.
Remaining on the rung
Both declared gates —
security-reviewandpentest. Running them next.🤖 Generated with Claude Code