Skip to content

feat: add end-to-end encrypted device sync#130

Open
debugtheworldbot wants to merge 2 commits into
mainfrom
codex/feat/e2ee-device-sync
Open

feat: add end-to-end encrypted device sync#130
debugtheworldbot wants to merge 2 commits into
mainfrom
codex/feat/e2ee-device-sync

Conversation

@debugtheworldbot

@debugtheworldbot debugtheworldbot commented Jul 14, 2026

Copy link
Copy Markdown
Owner

Summary

  • Add privacy-preserving, end-to-end encrypted device sync for up to five macOS and Windows devices.
  • Keep statistics and device metadata encrypted client-side while Cloudflare stores only opaque identifiers and ciphertext.
  • Add shared protocol contracts, automated coverage, and CI/deployment workflows for the sync service.

Changes

  • Implement macOS and Windows sync coordinators, cryptography, credential storage, aggregation, scheduling, and settings UI.
  • Add a Cloudflare Worker backed by D1 and R2 for vaults, pairing, recovery, sync history, revocation, and cleanup.
  • Define versioned OpenAPI/JSON schemas and cross-platform crypto fixtures.
  • Add Swift, .NET, and Worker test suites plus staging/production deployment workflows.
  • Stabilize macOS sync settings initialization and project configuration.

Test Plan

  • Run swift test.
  • Run xcodebuild -project KeyStats.xcodeproj -scheme KeyStats -configuration Debug build.
  • Run dotnet test KeyStats.Windows/KeyStats.sln.
  • Run npm ci && npm run check in services/sync-worker.
  • Validate vault creation, pairing, recovery, sync, revocation, and deletion against staging.

Copilot AI review requested due to automatic review settings July 14, 2026 03:48

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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-worker with 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 without pipefail: if xcodebuild fails but xcpretty exits 0, the pipeline exits 0 and the fallback never runs. Enabling pipefail before 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";
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.

2 participants