Back to Blocks

Claude Terminal

Loading...

Task Details
PXL-701Ready
High

🔐 Stop silent ID changes

b2-heradatasync
Overview

This task addresses a critical security and data integrity concern: handling scenarios where a user's CloudKit ID changes silently when they switch CloudKit accounts on their device and return to the app.

CloudKit Account Change Scenarios

A user's CloudKit ID can change in several situations:

  • User signs out of iCloud and signs in with a different Apple ID
  • User changes their primary Apple ID in device settings
  • User switches between multiple iCloud accounts configured on the device
  • Family Sharing account transitions
  • Device restoration or migration scenarios
Current Behavior Investigation

Phase 1: Understanding Current State

  1. Analyze how the app currently stores and uses CloudKit user identifiers
  2. Review the SyncCoordinator and SyncEngine implementations in /Users/pxlshpr/Developer/NutriKit/Packages/App/Sources/App/Supabase/ to understand CloudKit integration points
  3. Determine if the app currently detects CloudKit account changes at all
  4. Map out all places in the codebase where CloudKit user identity is assumed to be stable
  5. Test actual behavior when switching CloudKit accounts mid-session
Potential Issues to Address

Data Sync Conflicts:

  • Local data associated with User A's CloudKit ID attempting to sync when User B is signed in
  • Orphaned records in CloudKit containers
  • Cross-contamination of user data between accounts

User Authentication Problems:

  • Session validity when CloudKit identity no longer matches
  • Authorization failures for CloudKit operations
  • Broken relationships between Supabase user records and CloudKit identities

Data Integrity Issues:

  • Food logs, meals, and health data attributed to wrong user account
  • Widget data showing information from previous user
  • Cache invalidation and stale user-specific data
  • Database records with mismatched CloudKit references

Privacy and Security Concerns:

  • User A's data being inadvertently synced to User B's CloudKit container
  • Exposure of sensitive health/nutrition data across accounts
Mitigation Strategies to Explore

1. CloudKit Account Change Detection

  • Implement monitoring using CKAccountChangedNotification or equivalent
  • Store the current CloudKit user record ID and compare on app launch/resume
  • Add app lifecycle hooks to verify CloudKit identity consistency

2. Graceful Account Transition Handling

  • Clear local cache and user-specific data when account change detected
  • Reset sync state and force fresh data pull from new account
  • Invalidate any CloudKit-dependent authentication tokens

3. User Communication

  • Present a clear alert/dialog when CloudKit account change is detected
  • Explain implications: "You've switched iCloud accounts. Your previous data will be cleared and you'll sync with your new account."
  • Provide option to sign out properly or acknowledge the transition

4. Data Migration/Cleanup Strategy

  • Define whether any data should be preserved locally vs. completely purged
  • Implement safe cleanup of CloudKit-tied resources
  • Ensure no data leakage between accounts
  • Log account transitions for debugging/audit purposes

5. Prevention Mechanisms

  • Consider requiring explicit sign-out before allowing account-dependent operations
  • Implement stronger binding between app session and CloudKit identity
  • Add validation checks before any sync operations
Implementation Considerations
  • Review Apple's CloudKit documentation on account change handling best practices
  • Consider impact on offline-first architecture and pending sync operations
  • Test extensively with multiple iCloud accounts, sign-out/sign-in flows
  • Ensure compatibility with existing user data and migration paths
  • Document the chosen approach in code and user-facing materials
Acceptance Criteria
  • Complete analysis of current CloudKit ID usage throughout codebase
  • Documented list of all potential failure scenarios
  • Implemented detection mechanism for CloudKit account changes
  • User-facing handling flow (alerts, cleanup, re-sync)
  • Comprehensive test coverage for account switching scenarios
  • No data leakage between different CloudKit accounts
  • Graceful degradation if CloudKit becomes unavailable during transition
Technical Context

This app uses CloudKit for data synchronization and has a sophisticated sync system via SyncCoordinator and SyncEngine. The codebase contains 47,000+ lines of Swift with features including meal tracking, Apple Health integration, and widgets. Recent changes removed isTrashed and isArchived fields, suggesting active data model evolution that makes this investigation timely.

Build instruction: Use -destination 'platform=iOS Simulator,name=iPhone 17 Pro' when building this project

Comments (1)
Ahmed Khalaf
Ahmed KhalafJan 11, 2026, 4:06 AM

Implementation Complete - CloudKit Account Change Detection

Analysis Summary

Critical Gap Found: The app had NO CloudKit account change detection. The CloudKit ID was fetched once on app launch and cached forever, never re-verified even when returning from background. This meant:

  • User A's data could be synced when User B is signed in
  • Cross-user data contamination was possible
  • Silent account switches went completely undetected

Files Created

1. Packages/App/Sources/App/Services/CloudKitAccountMonitor.swift

  • Singleton service monitoring CKAccountChangedNotification
  • Verifies CloudKit ID on every foreground transition
  • Compares stored ID vs current ID to detect changes
  • Posts cloudKitAccountChanged notification on mismatch
  • Provides methods: verifyAccount(), acknowledgeAccountChange(), clearStoredIdentity(), refreshCloudKitID()

2. Packages/App/Sources/App/Views/AccountChangedAlert.swift

  • User-facing alert when account change detected
  • Options: "Continue with New Account" or "Sign Out of App"
  • Shows previous/current CloudKit IDs for transparency
  • Different messaging for sign-out vs account switch

Files Modified

NutriKit/NutriKitApp.swift:

  • Added @StateObject for CloudKitAccountMonitor
  • Added showingAccountChangedAlert state
  • Updated fetchCloudKitID() to use account monitor
  • Added verifyCloudKitAccount() - called on every foreground
  • Updated scenePhaseChanged() - verifies account before operations
  • Updated performSupabaseSync() - blocks sync when change pending
  • Added handleContinueWithNewAccount() - clears sync state, restarts
  • Added handleSignOutFromApp() - clears all identity data
  • Added clearSyncState() - marks all local data as unsynced

Security Flow

Foreground Transition
        │
        ▼
   verifyAccount()
        │
        ▼
Compare stored vs current CloudKit ID
        │
   ┌────┼────┐
   ▼    ▼    ▼
Match  Mismatch  No Account
  │       │         │
  ▼       ▼         ▼
Continue  BLOCK     BLOCK
 sync     SYNC      SYNC
          Show      Show
          Alert     Alert

Acceptance Criteria

  • ✅ Detection mechanism for CloudKit account changes
  • ✅ User-facing handling flow (alerts, cleanup, re-sync)
  • ✅ No data leakage between accounts (sync blocked until acknowledged)
  • ✅ Graceful degradation if CloudKit unavailable

Status: Ready for build & testing

Created Dec 7, 2025, 3:02 AM | Updated Feb 6, 2026, 11:40 AM