Repository navigation
Conversation
sanitz
force-pushed
the
feat/sync-ical-subscriptions
branch
from
September 19, 2026 15:21
ea979cc to
e2948aa
Compare
…s them Since subscriptions record their owning login (server plus login name), syncing them through the settings blob has to respect that owner: - The parser dropped the owner field, so every synced copy lost it and could again be refreshed or removed through an unrelated login. - Each account's server blob received every local subscription, so one login's secret feed URLs were stored in another login's settings, and subscriptions forgotten on sign-out came back with the next load. Keep the owner when parsing, push only the active login's subscriptions into its blob, and on a server load ignore subscriptions owned by another login. Unowned (older) entries still load and are adopted by claimSubscription() only once their calendar is found. The owner key is built in one place, subscriptionOwnerFor(), which subscriptionOwner() now uses. The store test's client mock gains getServerUrl/getUsername. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This branch has not been deployed
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.
Description
This PR persists and syncs iCal calendar subscriptions (
icalSubscriptions) and their deletion tombstones (deletedSubscriptionIds) via Bulwark's existing encrypted settings synchronization (SETTINGS_SYNC_ENABLED), using the same bridge pattern introduced for email templates in #825 (CalendarSubscriptionSyncBridge).Context & Problem Solved
Subscriptions becoming regular/writable calendars on cache reset:
When a user subscribes to an external iCal feed, Bulwark creates a JMAP calendar on the backend and stores the feed metadata (
icalSubscriptions) only in browserlocalStorage. If that is cleared, the metadata is lost and the calendar falls back to a standard writable personal calendar, inviting accidental edits.Cross-device subscription sync:
A subscription added on one device was not known on the user's other devices.
Changes
lib/calendar-subscription-sync.ts:mergeSyncedSubscriptions: conflict-free merge of local and server state (newerupdatedAtwins, deletion tombstones with TTL, a later edit resurrects a deleted subscription).parseSyncedSubscriptions,parseSubscriptionTombstones).subscriptionOwnerFor(serverUrl, username): the owner key, now also used bysubscriptionOwner().stores/calendar-store.ts:CalendarSubscriptionSyncBridgeto push subscriptions and tombstones into the encrypted settings payload.deletedSubscriptionIdswhen a subscription is removed, so deletions propagate across devices.applySyncedStatemerges incoming remote subscriptions without disrupting active UI state.stores/settings-store.ts:icalSubscriptionsanddeletedSubscriptionIds.exportSettingsandimportSettings.Per-login ownership
Subscriptions record their owning login (
owner, server plus login name, #5cc3ddba). The sync respects it:parseSyncedSubscriptionskeepsowner.claimSubscription()only once their calendar id and name are found in the account.Testing Done
lib/__tests__/calendar-subscription-sync.test.ts,stores/__tests__/calendar-subscription-sync.test.tsandstores/__tests__/settings-store-sync.test.ts(merge, tombstones, corrupted payloads, owner kept, owner-filtered export and import).--pool=forks --maxWorkers=2 --testTimeout=15000): 5240 passed.tsc --noEmitclean.