# Developer Account Migration Guide

This document provides a comprehensive guide for migrating the BusinessCard app from the personal `mbrucedogs` developer account to a new Apple Developer account.

## Quick Migration (xcconfig)

With the xcconfig setup, migration is now a **single file change**:

1. Open `BusinessCard/Configuration/Base.xcconfig`
2. Update these two lines:
   ```
   COMPANY_IDENTIFIER = com.newcompany
   DEVELOPMENT_TEAM = NEW_TEAM_ID
   ```
3. Clean build (⇧⌘K) and rebuild

That's it! All bundle IDs, entitlements, and Swift code will automatically use the new values.

---

## Current State Analysis

### Account Information
- **Current Team ID**: `6R7KLBPBLZ`
- **Current Bundle ID Prefix**: `com.mbrucedogs`

### Targets and Bundle Identifiers

| Target | Current Bundle ID |
|--------|------------------|
| iOS App | `com.mbrucedogs.BusinessCard` |
| Watch App | `com.mbrucedogs.BusinessCard.watchkitapp` |
| Tests | `com.mbrucedogs.BusinessCardTests` |
| UI Tests | `com.mbrucedogs.BusinessCardUITests` |
| App Clip (planned) | `com.mbrucedogs.BusinessCard.Clip` |

### Entitlements and Services

| Service | Current Identifier | Migration Impact |
|---------|-------------------|------------------|
| CloudKit Container | `iCloud.com.mbrucedogs.BusinessCard` | **HIGH** - Data loss risk |
| App Group | `group.com.mbrucedogs.BusinessCard` | Medium - Local data only |
| Push Notifications | `aps-environment: development` | Low - Re-register |
| Associated Domains (planned) | `appclips:cards.example.com` | Low - Domain-based |

---

## Migration Complexity Rating: MODERATE-HIGH

The main complexity comes from CloudKit. If users have data stored in CloudKit, changing the container identifier means:
- Users lose access to their synced data
- No automatic migration path exists
- Manual data export/import would be required

---

## Pre-Migration Checklist

### Before You Start

- [ ] Create the new Apple Developer Account
- [ ] Note the new Team ID (found in Membership section of developer portal)
- [ ] Decide on new bundle ID prefix (e.g., `com.newcompany`)
- [ ] Plan for CloudKit data migration (if app is in production)
- [ ] If app is NOT yet released, migration is straightforward

---

## Migration Steps

### Step 1: Update Team ID in Xcode

**Files affected**: `project.pbxproj`

1. Open project in Xcode
2. Select project in navigator
3. For each target, go to **Signing & Capabilities**
4. Change **Team** dropdown to new account
5. Xcode will update `DEVELOPMENT_TEAM` in 9 places

**Or manually replace in** `BusinessCard.xcodeproj/project.pbxproj`:
```
Find:    DEVELOPMENT_TEAM = 6R7KLBPBLZ;
Replace: DEVELOPMENT_TEAM = NEW_TEAM_ID;
```

---

### Step 2: Update Bundle Identifiers

**Files affected**: `project.pbxproj`

| Old | New |
|-----|-----|
| `com.mbrucedogs.BusinessCard` | `com.newcompany.BusinessCard` |
| `com.mbrucedogs.BusinessCard.watchkitapp` | `com.newcompany.BusinessCard.watchkitapp` |
| `com.mbrucedogs.BusinessCardTests` | `com.newcompany.BusinessCardTests` |
| `com.mbrucedogs.BusinessCardUITests` | `com.newcompany.BusinessCardUITests` |

1. In Xcode, select each target
2. Update **Bundle Identifier** in General tab
3. Verify watch app bundle ID is prefixed with iOS app bundle ID

---

### Step 3: Update CloudKit Container

**Files affected**: `BusinessCard/BusinessCard.entitlements`

```xml
<!-- Old -->
<key>com.apple.developer.icloud-container-identifiers</key>
<array>
    <string>iCloud.com.mbrucedogs.BusinessCard</string>
</array>

<!-- New -->
<key>com.apple.developer.icloud-container-identifiers</key>
<array>
    <string>iCloud.com.newcompany.BusinessCard</string>
</array>
```

**CRITICAL**: This creates a NEW, EMPTY CloudKit container. See Data Migration section below.

---

### Step 4: Update App Group

**Files affected**: `BusinessCard/BusinessCard.entitlements`

```xml
<!-- Old -->
<key>com.apple.security.application-groups</key>
<array>
    <string>group.com.mbrucedogs.BusinessCard</string>
</array>

<!-- New -->
<key>com.apple.security.application-groups</key>
<array>
    <string>group.com.newcompany.BusinessCard</string>
</array>
```

**Impact**: App Group is used for sharing data between the iOS app and extensions (not watch). Local data in the old group will be inaccessible.

---

### Step 5: Register New Identifiers in Developer Portal

In the new Apple Developer account portal:

1. **Identifiers > App IDs**
   - Register `com.newcompany.BusinessCard`
   - Register `com.newcompany.BusinessCard.watchkitapp`
   - Register `com.newcompany.BusinessCard.Clip` (for App Clip)

2. **Identifiers > iCloud Containers**
   - Create `iCloud.com.newcompany.BusinessCard`

3. **Identifiers > App Groups**
   - Create `group.com.newcompany.BusinessCard`

4. **Certificates, Identifiers & Profiles**
   - Create new provisioning profiles for all targets
   - Xcode can auto-manage this if "Automatically manage signing" is enabled

---

### Step 6: Update Code References

Search and replace in codebase for hardcoded identifiers.

**Files to check** (based on grep results):
- `BusinessCard/BusinessCardApp.swift`
- `README.md`
- `ai_implementation.md`
- Any service files referencing container IDs

**Search for**:
```
com.mbrucedogs
iCloud.com.mbrucedogs
group.com.mbrucedogs
```

**Example in SharedCardCloudKitService** (from OPUS plan):
```swift
// Update default parameter
init(containerID: String = "iCloud.com.newcompany.BusinessCard", ...)
```

---

### Step 7: Update Associated Domains (If App Clip Implemented)

**Files affected**: Both iOS app and App Clip entitlements

The domain itself (`cards.example.com`) doesn't change, but the server's `apple-app-site-association` file needs the new Team ID:

```json
{
  "appclips": {
    "apps": ["NEW_TEAM_ID.com.newcompany.BusinessCard.Clip"]
  },
  "applinks": {
    "apps": [],
    "details": [{
      "appID": "NEW_TEAM_ID.com.newcompany.BusinessCard",
      "paths": ["/appclip/*"]
    }]
  }
}
```

---

## CloudKit Data Migration

### Scenario A: App Not Yet Released

**Effort**: None

If the app hasn't been released to users, there's no data to migrate. Simply use the new container.

### Scenario B: App Released, Minimal Users

**Effort**: Low

1. Communicate to users that data will reset
2. Provide in-app export feature before migration (export to vCard files)
3. After update, users re-import their cards

### Scenario C: App Released, Significant Users

**Effort**: HIGH

CloudKit doesn't support container migration. Options:

#### Option 1: Dual Container (Recommended)

Keep access to both containers temporarily:

```xml
<key>com.apple.developer.icloud-container-identifiers</key>
<array>
    <string>iCloud.com.mbrucedogs.BusinessCard</string>
    <string>iCloud.com.newcompany.BusinessCard</string>
</array>
```

Then implement in-app migration:
1. On launch, check old container for data
2. Copy records to new container
3. Delete from old container
4. Remove old container access in future update

**Complexity**: Requires both accounts to grant container access, or the old account must add the new Team ID to the old container's permissions.

#### Option 2: Backend Migration Service

1. Build a server that can access both containers
2. Migrate data server-side
3. Coordinate with app update

**Complexity**: Requires server infrastructure and CloudKit server-to-server keys.

#### Option 3: User-Initiated Export/Import

1. Add "Export All Cards" feature (before migration)
2. Export to files (vCard, JSON, or iCloud Drive)
3. Release update with new container
4. Add "Import Cards" feature
5. Users manually export/import

**Complexity**: Lowest technical effort, but poor user experience.

---

## SwiftData Considerations

SwiftData with CloudKit uses the CloudKit container for sync. When the container changes:

- **Private database records**: Lost (unless migrated)
- **Local SwiftData store**: Remains on device but stops syncing
- **New installs**: Start fresh with empty database

If using SwiftData's automatic CloudKit sync, consider:
1. Disable CloudKit sync temporarily during migration
2. Keep local data intact
3. Re-enable sync with new container
4. Local data will upload to new container

---

## Watch App Considerations

The watch app uses WatchConnectivity (not App Groups) for data sync, so:
- **Bundle ID change**: Required (must match iOS app prefix)
- **Data sync**: Unaffected (syncs from iOS app)
- **Re-pairing**: May need to reinstall watch app after bundle ID change

---

## App Store Considerations

### Same Account, New Bundle ID
- This is a NEW app listing
- Lose reviews, ratings, download history
- Can reference old app in description

### App Transfer (Same Bundle ID)
- If keeping the same bundle ID but transferring ownership
- Use App Store Connect's "Transfer App" feature
- Preserves reviews, ratings, users
- **Requires**: Both accounts in good standing, no active TestFlight, no pending updates

### Recommendation

If possible, use **App Transfer** to maintain continuity. This requires:
1. Old account initiates transfer
2. New account accepts transfer
3. Bundle ID stays the same
4. Only Team ID changes in project
5. CloudKit container permissions may need updates

---

## Complete File Change Summary

| File | Changes Required |
|------|------------------|
| `project.pbxproj` | Team ID (9 places), Bundle IDs (6 places) |
| `BusinessCard.entitlements` | CloudKit container, App Group |
| `BusinessCardWatch.entitlements` | None (currently empty) |
| `SharedCardCloudKitService.swift` | Container ID parameter |
| `README.md` | Update any bundle ID references |
| `ai_implementation.md` | Update any bundle ID references |
| Server AASA file | Update Team ID |

---

## Testing After Migration

1. **Clean build**: Delete derived data, clean build folder
2. **Fresh install**: Delete app from device, reinstall
3. **CloudKit Dashboard**: Verify new container is receiving data
4. **Watch app**: Verify watch installs and syncs correctly
5. **Push notifications**: Verify registration with new bundle ID
6. **App Clip**: Test invocation URL with new Team ID

---

## Timeline Estimate

| Phase | Duration |
|-------|----------|
| Preparation (new account setup) | 1-2 days |
| Code changes | 1-2 hours |
| Testing | 1-2 days |
| CloudKit data migration (if needed) | 1-2 weeks |
| App Store transition | 1-3 days |

---

## Recommendation

**If the app is not yet released**: Migrate now while it's simple.

**If the app is released**: Consider using App Transfer to keep the same bundle ID and minimize disruption. You'll still need to update the Team ID and potentially CloudKit container access.

---

*Last updated: January 10, 2026*
