diff --git a/doc/activeDid-migration-plan.md b/doc/activeDid-migration-plan.md
index 9329a6f5..0b954e99 100644
--- a/doc/activeDid-migration-plan.md
+++ b/doc/activeDid-migration-plan.md
@@ -1,91 +1,50 @@
-# ActiveDid Migration Plan - Separate Table Architecture
+# ActiveDid Migration Plan - Implementation Guide
**Author**: Matthew Raymer
**Date**: 2025-08-29T08:03Z
-**Status**: 🎯 **PLANNING** - Active migration planning phase
+**Status**: 🎯 **IMPLEMENTATION** - Ready for development
## Objective
-Move the `activeDid` field from the `settings` table to a dedicated
-`active_identity` table to improve database architecture, prevent data corruption,
-and separate identity selection from user preferences.
+Move the `activeDid` field from the `settings` table to a dedicated `active_identity` table to improve database architecture, prevent data corruption, and separate identity selection from user preferences.
## Result
-This document serves as the comprehensive planning and implementation
-guide for the ActiveDid migration with enhanced data integrity and
-rollback capabilities.
+This document provides the specific implementation steps required to complete the ActiveDid migration with all necessary code changes.
## Use/Run
-Reference this document during implementation to ensure all migration
-steps are followed correctly and all stakeholders are aligned on the
-approach.
+Follow this implementation checklist step-by-step to complete the migration.
## Context & Scope
-- **In scope**:
- - Database schema modification for active_identity table with proper constraints
- - Migration of existing activeDid data with validation
- - Updates to PlatformServiceMixin API layer
- - Type definition updates
- - Testing across all platforms
- - Comprehensive rollback procedures
-- **Out of scope**:
- - Changes to user interface for identity selection
- - Modifications to identity creation logic
- - Changes to authentication flow
- - Updates to individual components (handled by API layer)
-
-## Environment & Preconditions
-
-- **OS/Runtime**: All platforms (Web, Electron, iOS, Android)
-- **Versions/Builds**: Current development branch, SQLite database
-- **Services/Endpoints**: Local database, PlatformServiceMixin
-- **Auth mode**: Existing authentication system unchanged
-
-## Architecture / Process Overview
-
-The migration follows a phased approach to minimize risk and ensure
-data integrity with enhanced validation and rollback capabilities:
-
-```mermaid
-flowchart TD
- A[Current State
activeDid in settings] --> B[Phase 1: Schema Creation
Add active_identity table with constraints]
- B --> C[Phase 2: Data Migration
Copy activeDid data with validation]
- C --> D[Phase 3: API Updates
Update PlatformServiceMixin methods]
- D --> E[Phase 4: Cleanup
Remove activeDid from settings]
- E --> F[Final State
Separate active_identity table]
-
- G[Enhanced Rollback Plan
Schema and data rollback] --> H[Data Validation
Verify integrity at each step]
- H --> I[Platform Testing
Test all platforms]
- I --> J[Production Deployment
Gradual rollout with monitoring]
-
- K[Foreign Key Constraints
Prevent future corruption] --> L[Performance Optimization
Proper indexing]
- L --> M[Error Recovery
Graceful failure handling]
-```
+- **In scope**: Database migration, API updates, component updates, testing
+- **Out of scope**: UI changes, authentication flow changes, MASTER_SETTINGS_KEY elimination (future improvement)
-## Interfaces & Contracts
+## Implementation Checklist
-### Database Schema Changes
+### Phase 1: Database Migration ✅
+- [x] Add migration to MIGRATIONS array
+- [x] Create active_identity table with constraints
-| Table | Current Schema | New Schema | Migration Required |
-|-------|----------------|------------|-------------------|
-| `settings` | `activeDid TEXT` | Field removed | Yes - data migration |
-| `active_identity` | Does not exist | New table with `activeDid TEXT` + constraints | Yes - table creation |
+### Phase 2: API Layer Updates ❌
+- [ ] Implement `$getActiveIdentity()` method
+- [ ] Update `$accountSettings()` to use new table
+- [ ] Update `$updateActiveDid()` with dual-write pattern
-### Enhanced API Contract Changes
+### Phase 3: Component Updates ❌
+- [ ] Update 35+ components to use `$getActiveIdentity()`
+- [ ] Replace `this.activeDid = settings.activeDid` pattern
+- [ ] Test each component individually
-| Method | Current Behavior | New Behavior | Breaking Change |
-|---------|------------------|--------------|-----------------|
-| `$accountSettings()` | Returns settings with activeDid | Returns settings with activeDid from new table | No - backward compatible |
-| `$saveSettings()` | Updates settings.activeDid | Updates active_identity.activeDid | Yes - requires updates |
-| `$updateActiveDid()` | Updates internal tracking | Updates active_identity table | Yes - requires updates |
-| `$getActiveIdentity()` | Does not exist | New method for active identity management | No - new functionality |
+### Phase 4: Testing ❌
+- [ ] Test all platforms (Web, Electron, iOS, Android)
+- [ ] Test migration rollback scenarios
+- [ ] Test data corruption recovery
-## Repro: End-to-End Procedure
+## Required Code Changes
-### Phase 1: Enhanced Schema Creation via migration.ts
+### 1. Database Migration
```typescript
// Add to MIGRATIONS array in src/db-sql/migration.ts
@@ -110,68 +69,50 @@ flowchart TD
},
```
-### Phase 2: Enhanced Data Migration with Validation
+### 2. Missing API Method Implementation
```typescript
-// Enhanced migration function with comprehensive validation
-async function migrateActiveDidToSeparateTable(): Promise {
- const result: MigrationResult = {
- success: false,
- errors: [],
- warnings: [],
- dataMigrated: 0
- };
-
+// Add to PlatformServiceMixin.ts
+async $getActiveIdentity(): Promise<{ activeDid: string }> {
try {
- // 1. Get current activeDid from settings (legacy approach)
- const currentSettings = await retrieveSettingsForDefaultAccount();
- const activeDid = currentSettings.activeDid;
-
- if (!activeDid) {
- result.warnings.push("No activeDid found in current settings");
- return result;
- }
-
- // 2. Validate activeDid exists in accounts table
- const accountExists = await dbQuery(
- "SELECT did FROM accounts WHERE did = ?",
- [activeDid]
+ const result = await this.$dbQuery(
+ "SELECT activeDid FROM active_identity WHERE id = 1"
);
-
- if (!accountExists?.values?.length) {
- result.errors.push(`ActiveDid ${activeDid} not found in accounts table - data corruption detected`);
- return result;
+
+ if (result?.values?.length) {
+ const activeDid = result.values[0][0] as string;
+
+ // Validate activeDid exists in accounts
+ if (activeDid) {
+ const accountExists = await this.$dbQuery(
+ "SELECT did FROM accounts WHERE did = ?",
+ [activeDid]
+ );
+
+ if (accountExists?.values?.length) {
+ return { activeDid };
+ } else {
+ // Clear corrupted activeDid
+ await this.$dbExec(
+ "UPDATE active_identity SET activeDid = '', lastUpdated = datetime('now') WHERE id = 1"
+ );
+ return { activeDid: "" };
+ }
+ }
}
-
- // 3. Update active_identity table (new system)
- await dbExec(
- "UPDATE active_identity SET activeDid = ?, lastUpdated = datetime('now') WHERE id = 1",
- [activeDid]
- );
-
- // 4. Ensure legacy settings.activeDid stays in sync (backward compatibility)
- // This maintains compatibility with IndexedDB migration service
- await dbExec(
- "UPDATE settings SET activeDid = ? WHERE id = ?",
- [activeDid, MASTER_SETTINGS_KEY]
- );
-
- dataMigrated = 1;
- result.warnings.push(`Successfully migrated activeDid: ${activeDid}`);
+ return { activeDid: "" };
} catch (error) {
- result.errors.push(`Migration failed: ${error}`);
- logger.error("[ActiveDid Migration] Critical error during migration:", error);
+ logger.error("[PlatformServiceMixin] Error getting active identity:", error);
+ return { activeDid: "" };
}
-
- return result;
}
```
-### Phase 3: Focused API Updates with Dual-Write Pattern
+### 3. Updated $accountSettings Method
```typescript
-// Updated PlatformServiceMixin method - maintains backward compatibility
+// Update in PlatformServiceMixin.ts
async $accountSettings(did?: string, defaults: Settings = {}): Promise {
try {
// Get settings without activeDid (unchanged logic)
@@ -182,7 +123,7 @@ async $accountSettings(did?: string, defaults: Settings = {}): Promise
}
// Get activeDid from new table (new logic)
- const activeIdentity = await this._getActiveIdentity();
+ const activeIdentity = await this.$getActiveIdentity();
// Return combined result (maintains backward compatibility)
return { ...settings, activeDid: activeIdentity.activeDid };
@@ -191,164 +132,161 @@ async $accountSettings(did?: string, defaults: Settings = {}): Promise
return defaults;
}
}
+```
-// Enhanced update activeDid method with dual-write pattern
-async $updateActiveDid(newDid: string | null): Promise {
- try {
- if (newDid === null) {
- // Clear active identity in both tables
- await this.$dbExec(
- "UPDATE active_identity SET activeDid = '', lastUpdated = datetime('now') WHERE id = 1"
- );
-
- // Keep legacy field in sync (backward compatibility)
- await this.$dbExec(
- "UPDATE settings SET activeDid = '' WHERE id = ?",
- [MASTER_SETTINGS_KEY]
- );
- } else {
- // Validate DID exists before setting
- const accountExists = await this.$dbQuery(
- "SELECT did FROM accounts WHERE did = ?",
- [newDid]
- );
+### 4. Component Updates Required
- if (!accountExists?.values?.length) {
- logger.error(`[PlatformServiceMixin] Cannot set activeDid to non-existent DID: ${newDid}`);
- return false;
- }
+**35+ components need this pattern change:**
- // Update active identity in new table
- await this.$dbExec(
- "UPDATE active_identity SET activeDid = ?, lastUpdated = datetime('now') WHERE id = 1",
- [newDid]
- );
-
- // Keep legacy field in sync (backward compatibility)
- await this.$dbExec(
- "UPDATE settings SET activeDid = ? WHERE id = ?",
- [newDid, MASTER_SETTINGS_KEY]
- );
- }
+```typescript
+// CURRENT PATTERN (replace in all components):
+this.activeDid = settings.activeDid || "";
- // Update internal tracking
- await this._updateInternalActiveDid(newDid);
- return true;
- } catch (error) {
- logger.error("[PlatformServiceMixin] Error updating activeDid:", error);
- return false;
- }
-}
+// NEW PATTERN (use in all components):
+const activeIdentity = await this.$getActiveIdentity();
+this.activeDid = activeIdentity.activeDid || "";
```
-### **Master Settings Functions Implementation Strategy**
-
-#### **1. Update `retrieveSettingsForDefaultAccount()`**
+**Components requiring updates:**
+
+#### Views (25 components)
+- `src/views/DIDView.vue` (line 378)
+- `src/views/TestView.vue` (line 654)
+- `src/views/ContactAmountsView.vue` (line 226)
+- `src/views/HomeView.vue` (line 517)
+- `src/views/UserProfileView.vue` (line 185)
+- `src/views/ClaimView.vue` (line 730)
+- `src/views/OfferDetailsView.vue` (line 435)
+- `src/views/QuickActionBvcEndView.vue` (line 229)
+- `src/views/SharedPhotoView.vue` (line 178)
+- `src/views/ClaimReportCertificateView.vue` (line 56)
+- `src/views/ProjectsView.vue` (line 393)
+- `src/views/ClaimAddRawView.vue` (line 114)
+- `src/views/ContactQRScanShowView.vue` (line 288)
+- `src/views/InviteOneAcceptView.vue` (line 122)
+- `src/views/RecentOffersToUserView.vue` (line 118)
+- `src/views/NewEditProjectView.vue` (line 380)
+- `src/views/GiftedDetailsView.vue` (line 443)
+- `src/views/ProjectViewView.vue` (line 782)
+- `src/views/ContactsView.vue` (line 296)
+- `src/views/ContactQRScanFullView.vue` (line 267)
+- `src/views/NewActivityView.vue` (line 204)
+- `src/views/ClaimCertificateView.vue` (line 42)
+- `src/views/ContactGiftingView.vue` (line 166)
+- `src/views/RecentOffersToUserProjectsView.vue` (line 126)
+- `src/views/InviteOneView.vue` (line 285)
+- `src/views/IdentitySwitcherView.vue` (line 202)
+- `src/views/AccountViewView.vue` (line 1052)
+- `src/views/ConfirmGiftView.vue` (line 549)
+- `src/views/ContactImportView.vue` (line 342)
+
+#### Components (10 components)
+- `src/components/OfferDialog.vue` (line 177)
+- `src/components/PhotoDialog.vue` (line 270)
+- `src/components/GiftedDialog.vue` (line 223)
+- `src/components/MembersList.vue` (line 234)
+- `src/components/OnboardingDialog.vue` (line 272)
+- `src/components/ImageMethodDialog.vue` (line 502)
+- `src/components/FeedFilters.vue` (line 89)
+
+**Implementation Strategy:**
+
+1. **Systematic Replacement**: Use grep search to find all instances
+2. **Pattern Matching**: Replace `this.activeDid = settings.activeDid` with new pattern
+3. **Error Handling**: Ensure proper error handling in each component
+4. **Testing**: Test each component individually after update
+
+**Example Component Update:**
```typescript
-// Enhanced implementation with active_identity table integration
-export async function retrieveSettingsForDefaultAccount(): Promise {
- const platform = PlatformServiceFactory.getInstance();
-
- // Get settings without activeDid
- const sql = "SELECT id, accountDid, apiServer, filterFeedByNearby, filterFeedByVisible, " +
- "finishedOnboarding, firstName, hideRegisterPromptOnNewContact, isRegistered, " +
- "lastName, lastAckedOfferToUserJwtId, lastAckedOfferToUserProjectsJwtId, " +
- "lastNotifiedClaimId, lastViewedClaimId, notifyingNewActivityTime, " +
- "notifyingReminderMessage, notifyingReminderTime, partnerApiServer, " +
- "passkeyExpirationMinutes, profileImageUrl, searchBoxes, showContactGivesInline, " +
- "showGeneralAdvanced, showShortcutBvc, vapid, warnIfProdServer, warnIfTestServer, " +
- "webPushServer FROM settings WHERE id = ?";
-
- const result = await platform.dbQuery(sql, [MASTER_SETTINGS_KEY]);
-
- if (!result) {
- return DEFAULT_SETTINGS;
- } else {
- const settings = mapColumnsToValues(result.columns, result.values)[0] as Settings;
-
- // Handle JSON parsing
- if (settings.searchBoxes) {
- settings.searchBoxes = JSON.parse(settings.searchBoxes);
- }
+// BEFORE (in any component):
+private async initializeSettings() {
+ const settings = await this.$accountSettings();
+ this.activeDid = settings.activeDid || "";
+ this.apiServer = settings.apiServer || "";
+}
- // Get activeDid from separate table
- const activeIdentityResult = await platform.dbQuery(
- "SELECT activeDid FROM active_identity WHERE id = 1"
- );
+// AFTER (in any component):
+private async initializeSettings() {
+ const settings = await this.$accountSettings();
+ const activeIdentity = await this.$getActiveIdentity();
+ this.activeDid = activeIdentity.activeDid || "";
+ this.apiServer = settings.apiServer || "";
+}
+```
- if (activeIdentityResult?.values?.length) {
- const activeDid = activeIdentityResult.values[0][0] as string;
- if (activeDid) {
- // Validate activeDid exists in accounts
- const accountExists = await platform.dbQuery(
- "SELECT did FROM accounts WHERE did = ?",
- [activeDid]
- );
-
- if (accountExists?.values?.length) {
- settings.activeDid = activeDid;
- } else {
- logger.warn(`[databaseUtil] ActiveDid ${activeDid} not found in accounts, clearing`);
- // Clear corrupted activeDid
- await platform.dbExec(
- "UPDATE active_identity SET activeDid = '', lastUpdated = datetime('now') WHERE id = 1"
- );
- }
- }
- }
+**Alternative Pattern (if settings still needed):**
- return settings;
- }
+```typescript
+// If component needs both settings and activeDid:
+private async initializeSettings() {
+ const settings = await this.$accountSettings();
+ const activeIdentity = await this.$getActiveIdentity();
+
+ // Use activeDid from new table
+ this.activeDid = activeIdentity.activeDid || "";
+
+ // Use other settings from settings table
+ this.apiServer = settings.apiServer || "";
+ this.partnerApiServer = settings.partnerApiServer || "";
+ // ... other settings
}
```
-#### **2. Update `$getMergedSettings()` Method**
+### 5. Data Migration Function
```typescript
-// Enhanced implementation with active_identity table integration
-async $getMergedSettings(defaultKey: string, accountDid?: string, defaultFallback: Settings = {}): Promise {
+// Add to migration.ts
+async function migrateActiveDidToSeparateTable(): Promise {
+ const result: MigrationResult = {
+ success: false,
+ errors: [],
+ warnings: [],
+ dataMigrated: 0
+ };
+
try {
- // Get default settings (now without activeDid)
- const defaultSettings = await this.$getSettings(defaultKey, defaultFallback);
-
- // If no account DID, return defaults with activeDid from separate table
- if (!accountDid) {
- if (defaultSettings) {
- // Get activeDid from separate table
- const activeIdentityResult = await this.$dbQuery(
- "SELECT activeDid FROM active_identity WHERE id = 1"
- );
+ // 1. Get current activeDid from settings (legacy approach)
+ const currentSettings = await retrieveSettingsForDefaultAccount();
+ const activeDid = currentSettings.activeDid;
- if (activeIdentityResult?.values?.length) {
- const activeDid = activeIdentityResult.values[0][0] as string;
- if (activeDid) {
- // Validate activeDid exists in accounts
- const accountExists = await this.$dbQuery(
- "SELECT did FROM accounts WHERE did = ?",
- [activeDid]
- );
-
- if (accountExists?.values?.length) {
- defaultSettings.activeDid = activeDid;
- } else {
- logger.warn(`[Settings Trace] ActiveDid ${activeDid} not found in accounts, clearing`);
- // Clear corrupted activeDid
- await this.$dbExec(
- "UPDATE active_identity SET activeDid = '', lastUpdated = datetime('now') WHERE id = 1"
- );
- }
- }
- }
- }
- return defaultSettings || defaultFallback;
+ if (!activeDid) {
+ result.warnings.push("No activeDid found in current settings");
+ return result;
}
- // ... rest of existing implementation for account-specific settings
+ // 2. Validate activeDid exists in accounts table
+ const accountExists = await dbQuery(
+ "SELECT did FROM accounts WHERE did = ?",
+ [activeDid]
+ );
+
+ if (!accountExists?.values?.length) {
+ result.errors.push(`ActiveDid ${activeDid} not found in accounts table - data corruption detected`);
+ return result;
+ }
+
+ // 3. Update active_identity table (new system)
+ await dbExec(
+ "UPDATE active_identity SET activeDid = ?, lastUpdated = datetime('now') WHERE id = 1",
+ [activeDid]
+ );
+
+ // 4. Ensure legacy settings.activeDid stays in sync (backward compatibility)
+ await dbExec(
+ "UPDATE settings SET activeDid = ? WHERE id = ?",
+ [activeDid, MASTER_SETTINGS_KEY]
+ );
+
+ result.dataMigrated = 1;
+ result.warnings.push(`Successfully migrated activeDid: ${activeDid}`);
+
} catch (error) {
- logger.error(`[Settings Trace] ❌ Failed to get merged settings:`, { defaultKey, accountDid, error });
- return defaultFallback;
+ result.errors.push(`Migration failed: ${error}`);
+ logger.error("[ActiveDid Migration] Critical error during migration:", error);
}
+
+ return result;
}
```
@@ -377,40 +315,38 @@ async $getMergedSettings(defaultKey: string, accountDid?: string, defaultFallbac
- **Hypothesis**: Table needs to be created as part of migration
- **Next probe**: Add migration to existing MIGRATIONS array
-- ❌ **Data corruption issues** with orphaned activeDid references
+- ❌ **Missing $getActiveIdentity() method** in PlatformServiceMixin
+ - **Time**: 2025-08-29T08:03Z
+ - **Evidence**: Method referenced in plan but not implemented
+ - **Hypothesis**: Method needs to be added to PlatformServiceMixin
+ - **Next probe**: Implement method with proper error handling
+
+- ❌ **35+ components need updates** to use new API
- **Time**: 2025-08-29T08:03Z
- - **Evidence**: `IdentitySwitcherView.vue:175` - `hasCorruptedIdentity` detection
- - **Hypothesis**: Current schema allows activeDid to point to non-existent accounts
- - **Next probe**: Implement foreign key constraints in new table
+ - **Evidence**: Grep search found 35+ instances of `this.activeDid = settings.activeDid`
+ - **Hypothesis**: All components need to be updated to use `$getActiveIdentity()`
+ - **Next probe**: Update each component individually and test
## Risks, Limits, Assumptions
- **Data Loss Risk**: Migration failure could lose activeDid values
- **Breaking Changes**: API updates required in PlatformServiceMixin
-- **Rollback Complexity**: Schema changes make rollback difficult
- **Testing Overhead**: All platforms must be tested with new structure
-- **Performance Impact**: Additional table join for activeDid retrieval
-- **Migration Timing**: Must be coordinated with other database changes
-- **Data Corruption**: Current system has documented corruption issues
-- **Foreign Key Constraints**: New constraints may prevent some operations
+- **Component Updates**: 35+ components need individual updates and testing
-## Enhanced Rollback Strategy
+## Rollback Strategy
-### **Schema Rollback**
+### Schema Rollback
```sql
-- If migration fails, restore original schema
DROP TABLE IF EXISTS active_identity;
-
--- Restore activeDid field to settings table if needed
-ALTER TABLE settings ADD COLUMN activeDid TEXT;
```
-### **Data Rollback**
+### Data Rollback
```typescript
// Rollback function to restore activeDid to settings table
async function rollbackActiveDidMigration(): Promise {
try {
- // Get activeDid from active_identity table
const activeIdentityResult = await dbQuery(
"SELECT activeDid FROM active_identity WHERE id = 1"
);
@@ -418,7 +354,6 @@ async function rollbackActiveDidMigration(): Promise {
if (activeIdentityResult?.values?.length) {
const activeDid = activeIdentityResult.values[0][0] as string;
- // Restore to settings table
await dbExec(
"UPDATE settings SET activeDid = ? WHERE id = ?",
[activeDid, MASTER_SETTINGS_KEY]
@@ -435,142 +370,49 @@ async function rollbackActiveDidMigration(): Promise {
}
```
-### **Rollback Triggers**
-- Migration validation fails
-- Data integrity checks fail
-- Performance regression detected
-- User reports data loss
-- Cross-platform inconsistencies found
-
## Next Steps
| Owner | Task | Exit Criteria | Target Date (UTC) |
|-------|------|---------------|-------------------|
-| Development Team | Add migration to existing MIGRATIONS array | Migration script integrated with existing system | 2025-08-30 |
-| Development Team | Update type definitions | Settings type updated, ActiveIdentity type created | 2025-08-30 |
-| Development Team | Update PlatformServiceMixin | Core methods updated and tested | 2025-08-31 |
-| Development Team | Implement foreign key constraints | Schema validation prevents corruption | 2025-08-31 |
+| Development Team | Add migration to MIGRATIONS array | Migration script integrated | 2025-08-30 |
+| Development Team | Implement $getActiveIdentity() method | Method added to PlatformServiceMixin | 2025-08-30 |
+| Development Team | Update $accountSettings method | Method updated and tested | 2025-08-30 |
+| Development Team | Update 35+ components | All components use new API | 2025-08-31 |
| QA Team | Platform testing | All platforms tested and verified | 2025-09-01 |
| Development Team | Deploy migration | Production deployment successful | 2025-09-02 |
+## Future Improvement: MASTER_SETTINGS_KEY Elimination
+
+**Not critical for this task** but logged for future improvement:
+
+```typescript
+// Current: WHERE id = "1"
+// Future: WHERE accountDid IS NULL
+
+// This eliminates the confusing concept of "master" settings
+// and uses a cleaner pattern for default settings
+```
+
## References
- [Database Migration Guide](./database-migration-guide.md)
- [Dexie to SQLite Mapping](./dexie-to-sqlite-mapping.md)
- [PlatformServiceMixin Documentation](./component-communication-guide.md)
-- [Migration Templates](./migration-templates/)
## Competence Hooks
-- *Why this works*: Separates concerns between identity selection and
- user preferences, prevents data corruption with foreign key constraints,
- centralizes identity management through API layer
-- *Common pitfalls*: Forgetting to implement foreign key constraints, not
- testing rollback scenarios, missing data validation during migration,
- over-engineering component updates when API layer handles everything
-- *Next skill unlock*: Advanced database schema design with constraints,
- migration planning with rollback strategies
-- *Teach-back*: Explain the four-phase migration approach and why each
- phase is necessary, especially the foreign key constraints
+- *Why this works*: Separates concerns between identity selection and user preferences, prevents data corruption with foreign key constraints
+- *Common pitfalls*: Forgetting to update all 35+ components, not implementing $getActiveIdentity() method, missing data validation during migration
+- *Next skill unlock*: Systematic component updates with grep search and testing
+- *Teach-back*: Explain why all components need updates and how to systematically find and replace the pattern
## Collaboration Hooks
+- **Reviewers**: Database team, PlatformServiceMixin maintainers, QA team
- **Sign-off checklist**:
- [ ] Migration script integrated with existing MIGRATIONS array
- - [ ] Foreign key constraints implemented and tested
- - [ ] PlatformServiceMixin updated and tested
+ - [ ] $getActiveIdentity() method implemented and tested
+ - [ ] All 35+ components updated to use new API
- [ ] Rollback procedures validated
- - [ ] Performance impact assessed
- - [ ] All stakeholders approve deployment timeline
-
-## Assumptions & Limits
-
-- Current activeDid values are valid and should be preserved
-- All platforms can handle the additional database table
-- Migration can be completed without user downtime
-- Rollback to previous schema is acceptable if needed
-- Performance impact of additional table join is minimal
-- Foreign key constraints will prevent future corruption
-- API layer updates will handle component compatibility
-
-## What Needs to Change
-
-### **1. Database Schema via migration.ts**
-- Add migration to existing MIGRATIONS array in `src/db-sql/migration.ts`
-- Create `active_identity` table with foreign key constraints
-- Add performance indexes
-- **Keep `activeDid` field in `settings` table temporarily** for backward compatibility
-- **Preserve `MASTER_SETTINGS_KEY = "1"`** for legacy migration support
-
-### **2. PlatformServiceMixin Methods**
-- `$accountSettings()` - integrate with new table while maintaining backward compatibility
-- `$saveSettings()` - handle activeDid in new table, sync with legacy field
-- `$updateActiveDid()` - validate and update new table, sync with legacy field
-- `$getActiveIdentity()` - new method for identity management
-
-### **3. Master Settings Functions**
-- `retrieveSettingsForDefaultAccount()` - integrate with new table while preserving legacy support
-- `$getMergedSettings()` - integrate with new table while preserving legacy support
-
-### **4. Type Definitions**
-- **Keep `activeDid` in Settings type temporarily** for backward compatibility
-- Create ActiveIdentity type for new table
-- Update related interfaces
-
-### **5. Legacy Compatibility**
-- **Preserve `MASTER_SETTINGS_KEY = "1"`** for IndexedDB migration service
-- **Maintain dual-write pattern** during transition period
-- **Ensure legacy clients can still migrate** from Dexie to SQLite
-
-## What Doesn't Need to Change
-
-- **All Vue components** - API layer handles migration transparently
-- **Platform services** - Use PlatformServiceMixin, no direct access
-- **User interface** - No changes to identity selection UI
-- **Authentication flow** - Existing system unchanged
-- **Component logic** - All activeDid handling through API methods
-- **Migration system** - Use existing migration.ts approach, not separate files
-- **IndexedDB migration service** - Must continue working for legacy clients
-
-## Enhanced Architecture: Dual-Write Pattern
-
-### **Phase 1: Add New Table (Current)**
-```typescript
-// Create active_identity table
-// Keep existing settings.activeDid for backward compatibility
-// Use dual-write pattern during transition
-```
-
-### **Phase 2: Dual-Write Pattern**
-```typescript
-// When updating activeDid:
-// 1. Update active_identity table (new system)
-// 2. Update settings.activeDid (legacy compatibility)
-// 3. Ensure both stay in sync
-```
-
-### **Phase 3: Future Cleanup (Not in Current Scope)**
-```typescript
-// Eventually:
-// 1. Remove activeDid from settings table
-// 2. Deprecate MASTER_SETTINGS_KEY
-// 3. Use pure accountDid IS NULL pattern
-// 4. Update IndexedDB migration service
-```
-
-## Backward Compatibility Requirements
-
-### **Critical: IndexedDB Migration Service**
-- **Must continue working** for users migrating from Dexie
-- **Must recognize `id = "1"`** as master settings
-- **Must preserve existing migration paths**
-
-### **Important: Legacy Database Operations**
-- **Must continue working** for existing SQLite databases
-- **Must handle both old and new patterns**
-- **Must not break existing queries**
-
-### **Desired: Cleaner Architecture**
-- **New operations** use `accountDid IS NULL` pattern
-- **Legacy operations** continue using `MASTER_SETTINGS_KEY`
-- **Gradual migration** toward cleaner patterns
\ No newline at end of file
+ - [ ] All platforms tested
+ - [ ] All stakeholders approve deployment timeline
\ No newline at end of file