feat: add end-to-end encrypted device sync#130
Open
debugtheworldbot wants to merge 2 commits into
Open
Conversation
Contributor
There was a problem hiding this comment.
Pull request overview
Adds a new end-to-end encrypted, privacy-preserving multi-device sync system spanning:
- A Cloudflare Worker + D1/R2 backend that stores only opaque identifiers and ciphertext.
- macOS and Windows client implementations for crypto, durable state/credentials, aggregation, and settings UI.
- Shared protocol contracts/fixtures plus CI and deployment workflows.
Changes:
- Introduce
services/sync-workerwith schema validation, D1 migrations, Miniflare/Vitest tests, and staging/production deployment workflows. - Add macOS sync initialization, sync aggregation, UI entry points, localization updates, and build-time injection of the sync service URL.
- Add Windows sync UI, DPAPI-backed credential/state stores, batching/scheduling helpers, tests, and build-time injection of the sync service URL.
Reviewed changes
Copilot reviewed 99 out of 103 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
| services/sync-worker/wrangler.jsonc | Worker config for local/staging/prod bindings and cron trigger. |
| services/sync-worker/vitest.config.ts | Vitest + Miniflare setup for Worker/D1/R2 tests. |
| services/sync-worker/tsconfig.json | TypeScript configuration for Worker + tests. |
| services/sync-worker/test/env.d.ts | Test-only Cloudflare Env typings. |
| services/sync-worker/test/apply-migrations.ts | Test setup to apply migrations and reset DB/R2 state. |
| services/sync-worker/src/validation.ts | Request validation helpers and canonical JSON encoding. |
| services/sync-worker/src/types.ts | Shared Worker types for DB rows and encrypted payloads. |
| services/sync-worker/src/index.ts | Worker entrypoint with routing, error handling, and security headers. |
| services/sync-worker/src/http.ts | JSON/body handling utilities + request shape validation. |
| services/sync-worker/src/env.ts | Env parsing and service limits/kill-switch logic. |
| services/sync-worker/src/crypto.ts | Worker-side hashing/id validation utilities. |
| services/sync-worker/src/auth.ts | Bearer token auth and rate limiting helpers. |
| services/sync-worker/scripts/write-deploy-config.mjs | CI deploy helper to bind per-env D1 IDs into wrangler config. |
| services/sync-worker/README.md | Worker setup, ops guidance, and privacy guarantees. |
| services/sync-worker/package.json | Worker scripts and devDependencies for validation/testing/deploy. |
| services/sync-worker/migrations/0001_initial.sql | Initial D1 schema for vaults/devices/history/pairing/rate limits. |
| services/sync-worker/migrations/0002_active_device_limit.sql | D1 trigger enforcing max active devices on insert. |
| services/sync-worker/migrations/0003_history_revision_monotonic.sql | D1 trigger enforcing monotonic history revisions. |
| services/sync-worker/migrations/0004_exempt_sync_page_limit.sql | D1 field + constraint for bootstrap page exemption limit. |
| services/sync-worker/migrations/0005_maintenance_state.sql | D1 table for maintenance cursor/state. |
| services/sync-worker/migrations/0006_recovery_and_pairing_replay.sql | D1 changes for pairing replay + active limit on reactivation. |
| services/sync-worker/migrations/0007_vault_deletion_receipts.sql | D1 receipts table/index for delete retry acknowledgment. |
| services/sync-worker/.gitignore | Ignore Node/Wrangler build artifacts and env files. |
| scripts/build_dmg.sh | Allow injecting sync service URL into macOS DMG build. |
| Package.swift | Set macOS 13 platform, add zh-Hant, add sync sources/tests. |
| KeyStatsTests/StatsModelsTests.swift | Update test data for new middle-click field. |
| KeyStats/zh-Hans.lproj/Localizable.strings | Add Simplified Chinese strings for sync UI + import/reset behavior. |
| KeyStats/Sync/DisplayStatsAggregator.swift | macOS aggregation of remote sync shards into display stats. |
| KeyStats/StatsModels.swift | Add middle-click stats + saturating nonnegative sum helpers. |
| KeyStats/SettingsViewController.swift | Add sync section, manage button, import gating, reset copy changes. |
| KeyStats/Info.plist | Add build-time injected KeyStatsSyncServiceURL key. |
| KeyStats/en.lproj/Localizable.strings | Add English strings for sync UI + import/reset behavior. |
| KeyStats/AppDelegate.swift | Start sync coordinator at app startup. |
| KeyStats/AllTimeStatsViewController.swift | Click ratio updates to use non-left click totals + safer math. |
| KeyStats.xcodeproj/project.pbxproj | Add sync sources/resources and sync URL build setting. |
| KeyStats.Windows/KeyStats/Views/SyncSettingsWindow.xaml | New Windows sync management window UI. |
| KeyStats.Windows/KeyStats/Views/SettingsWindow.xaml.cs | Display sync status + open sync settings; gate import via sync. |
| KeyStats.Windows/KeyStats/Views/SettingsWindow.xaml | Add Sync card and name import button for enable/tooltip updates. |
| KeyStats.Windows/KeyStats/Services/SyncStateStore.cs | Durable sync state persistence with repair + backup handling. |
| KeyStats.Windows/KeyStats/Services/SyncServiceConfiguration.cs | Read and validate sync base URL from assembly metadata. |
| KeyStats.Windows/KeyStats/Services/SyncPendingSecretsStore.cs | DPAPI-protected persistence for in-flight create/recover/pairing secrets. |
| KeyStats.Windows/KeyStats/Services/SyncKeyCanonicalizer.cs | Canonicalize per-key names across Windows/macOS for sync. |
| KeyStats.Windows/KeyStats/Services/SyncCredentialStore.cs | DPAPI-protected persistence for sync credentials with binding checks. |
| KeyStats.Windows/KeyStats/Services/SyncBatchPlanner.cs | Build sync request batches and handle rollover archive ordering. |
| KeyStats.Windows/KeyStats/Services/StatsManager.cs | Integrate remote shard aggregation into stats ranges/queries; gate import; export scope. |
| KeyStats.Windows/KeyStats/Services/DisplayStatsAggregator.cs | Windows aggregation of remote shards into display stats. |
| KeyStats.Windows/KeyStats/Properties/Strings.zh-Hant.resx | Traditional Chinese strings updates + new sync strings. |
| KeyStats.Windows/KeyStats/Properties/Strings.zh-Hans.resx | Simplified Chinese strings updates + new sync strings. |
| KeyStats.Windows/KeyStats/Properties/Strings.resx | English strings updates + new sync strings. |
| KeyStats.Windows/KeyStats/Properties/Strings.cs | Add strongly-typed accessors for new strings. |
| KeyStats.Windows/KeyStats/KeyStats.csproj | Add sync base-url metadata, crypto dependency, extra framework refs. |
| KeyStats.Windows/KeyStats/App.xaml.cs | Initialize/start sync coordinator; show sync window; gate import; dispose on exit. |
| KeyStats.Windows/KeyStats.Sync.Tests/TestPlatform.cs | Windows-only test helper for DPAPI dependent tests. |
| KeyStats.Windows/KeyStats.Sync.Tests/TestDirectory.cs | Temp directory helper for sync tests. |
| KeyStats.Windows/KeyStats.Sync.Tests/SyncStateStoreTests.cs | Tests for durable state recovery/repair behaviors. |
| KeyStats.Windows/KeyStats.Sync.Tests/SyncSchedulingTests.cs | Tests for repair behavior and one-device scheduling gate. |
| KeyStats.Windows/KeyStats.Sync.Tests/SyncCryptoFixtureTests.cs | Validate Windows crypto against shared cross-platform fixtures. |
| KeyStats.Windows/KeyStats.Sync.Tests/SyncCredentialStoreTests.cs | Tests for credential + pending-secret DPAPI stores. |
| KeyStats.Windows/KeyStats.Sync.Tests/SyncCoordinatorHistoryResumeTests.cs | Tests for history-only resume behavior without posting /sync. |
| KeyStats.Windows/KeyStats.Sync.Tests/SyncBatchPlannerTests.cs | Tests for batching logic and idempotency fingerprint behavior. |
| KeyStats.Windows/KeyStats.Sync.Tests/RemoteShardCacheTests.cs | Tests for cache idempotency/conflict and durability recovery. |
| KeyStats.Windows/KeyStats.Sync.Tests/KeyStats.Sync.Tests.csproj | New MSTest project wired to shared fixtures. |
| KeyStats.Windows/KeyStats.Sync.Tests/AssemblyAttributes.cs | Disable test parallelization to avoid shared-state/DPAPI issues. |
| KeyStats.Windows/KeyStats.sln | Add new sync test project to solution. |
| KeyStats.Windows/build.ps1 | Support injecting sync base URL at build time. |
| docs/superpowers/specs/2026-07-13-e2ee-sync-design.md | Detailed E2EE sync design/spec document. |
| docs/superpowers/plans/2026-07-13-e2ee-sync.md | Implementation plan + verification gates and local verification status. |
| contracts/sync/v1/README.md | Protocol v1 source of truth and crypto/validation conventions. |
| contracts/sync/v1/fixtures/key-canonicalization.json | Cross-platform key canonicalization and date validation fixtures. |
| contracts/sync/v1/fixtures/crypto-vectors.json | Cross-platform deterministic crypto vectors. |
| contracts/sync/v1/encrypted-record.schema.json | JSON Schema for encrypted record envelope. |
| contracts/sync/v1/core-day-snapshot.schema.json | JSON Schema for plaintext snapshot before encryption. |
| contracts/sync/v1/api.schema.json | Shared API schema defs for requests/responses/errors. |
| .github/workflows/windows-sync-tests.yml | CI to run Windows .NET Framework sync tests on Windows runners. |
| .github/workflows/sync-worker-deploy-staging.yml | Main-branch staging deploy workflow for the Worker. |
| .github/workflows/sync-worker-deploy-production.yml | Manually approved production deploy workflow for the Worker. |
| .github/workflows/sync-worker-ci.yml | PR CI for contracts + migrations + typecheck + Miniflare/Vitest tests. |
| .github/workflows/release.yml | Inject production sync URL into macOS/Windows release builds and validate format. |
Comments suppressed due to low confidence (1)
scripts/build_dmg.sh:43
- The
xcodebuild | xcpretty || xcodebuild ...fallback is unreliable withoutpipefail: ifxcodebuildfails butxcprettyexits 0, the pipeline exits 0 and the fallback never runs. Enablingpipefailbefore the pipeline ensures failures propagate correctly.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Comment on lines
+1
to
+13
| import path from "node:path"; | ||
| import { cloudflareTest, readD1Migrations } from "@cloudflare/vitest-pool-workers"; | ||
| import { defineConfig } from "vitest/config"; | ||
|
|
||
| export default defineConfig({ | ||
| plugins: [ | ||
| cloudflareTest(async () => ({ | ||
| wrangler: { configPath: "./wrangler.jsonc" }, | ||
| miniflare: { | ||
| bindings: { | ||
| TOKEN_HASH_KEY: "test-only-token-hash-key-with-at-least-32-bytes", | ||
| TEST_MIGRATIONS: await readD1Migrations(path.join(import.meta.dirname, "migrations")), | ||
| }, |
| return operation(); | ||
| } catch (error) { | ||
| if (error instanceof ApiError) throw error; | ||
| throw new ApiError(400, "invalid_request", error instanceof Error ? error.message : "Request is invalid"); |
Comment on lines
+13
to
+17
| const source = JSON.parse(await readFile(new URL("../wrangler.jsonc", import.meta.url), "utf8")); | ||
| const target = source.env?.[environment]; | ||
| if (!target || !Array.isArray(target.d1_databases) || target.d1_databases.length !== 1) { | ||
| throw new Error(`wrangler.jsonc does not define exactly one D1 binding for ${environment}`); | ||
| } |
| INFOPLIST_FILE = KeyStats/Info.plist; | ||
| INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.utilities"; | ||
| INFOPLIST_KEY_NSHumanReadableCopyright = ""; | ||
| KEYSTATS_SYNC_SERVICE_URL = "https://keystats-sync-staging.istiancz.workers.dev"; |
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.
Summary
Changes
Test Plan
swift test.xcodebuild -project KeyStats.xcodeproj -scheme KeyStats -configuration Debug build.dotnet test KeyStats.Windows/KeyStats.sln.npm ci && npm run checkinservices/sync-worker.