@ -1,8 +1,8 @@
# ActiveDid Migration Plan - Separate Table Architecture
# ActiveDid Migration Plan - Separate Table Architecture
**Author**: Matthew Raymer
**Author**: Matthew Raymer
**Date**: 2025-08-29T08:03 Z
**Date**: 2025-08-29T15:00 Z
**Status**: 🎯 **PLANNING** - Active migration planning phas e
**Status**: 🎯 **IMPLEMENTATION READY** - Streamlined for existing migration servic e
## Objective
## Objective
@ -12,15 +12,14 @@ and separate identity selection from user preferences.
## Result
## Result
This document serves as the comprehensive planning and implementation
This document serves as the focused implementation guide for the ActiveDid
guide for the ActiveDid migration with enhanced data integrity and
migration, integrated with the existing IndexedDB migration service.
rollback capabilities.
## Use/Run
## Use/Run
Reference this document during implementation to ensure all migration
Reference this document during implementation to ensure all migration
steps are followed correctly and all stakeholders are aligned on the
steps are followed correctly. **Critical** : This plan integrates with the
approach .
existing `indexedDBMigrationService.ts` and maintains backward compatibility .
## Context & Scope
## Context & Scope
@ -28,9 +27,7 @@ approach.
- Database schema modification for active_identity table with proper constraints
- Database schema modification for active_identity table with proper constraints
- Migration of existing activeDid data with validation
- Migration of existing activeDid data with validation
- Updates to PlatformServiceMixin API layer
- Updates to PlatformServiceMixin API layer
- Type definition updates
- Integration with existing IndexedDB migration service
- Testing across all platforms
- Comprehensive rollback procedures
- **Out of scope** :
- **Out of scope** :
- Changes to user interface for identity selection
- Changes to user interface for identity selection
- Modifications to identity creation logic
- Modifications to identity creation logic
@ -41,51 +38,47 @@ approach.
- **OS/Runtime** : All platforms (Web, Electron, iOS, Android)
- **OS/Runtime** : All platforms (Web, Electron, iOS, Android)
- **Versions/Builds** : Current development branch, SQLite database
- **Versions/Builds** : Current development branch, SQLite database
- **Services/Endpoints** : Local database, PlatformServiceMixin
- **Services/Endpoints** : Local database, PlatformServiceMixin, indexedDBMigrationService
- **Auth mode** : Existing authentication system unchanged
- **Auth mode** : Existing authentication system unchanged
## Architecture / Process Overview
## Architecture / Process Overview
The migration follows a phased approach to minimize risk and ensure
The migration integrates with the existing IndexedDB migration service:
data integrity with enhanced validation and rollback capabilities:
```mermaid
```mermaid
flowchart TD
flowchart TD
A[Current State< br / > activeDid in settings] --> B[Phase 1: Schema Creation< br / > Add active_identity table with constraints]
A[Current State< br / > activeDid in settings] --> B[Phase 1: Schema Creation< br / > Add active_identity table with constraints]
B --> C[Phase 2: Data Migration< br / > Copy activeDid data with validation]
B --> C[Phase 2: Data Migration< br / > Copy activeDid data with validation]
C --> D[Phase 3: API Updates< br / > Update PlatformServiceMixin methods]
C --> D[Phase 3: API Updates< br / > Update PlatformServiceMixin methods]
D --> E[Phase 4: Cleanup< br / > Remove activeDid from settings]
D --> E[Final State< br / > Separate active_identity table + dual-write]
E --> F[Final State< br / > Separate active_identity table]
G[Enhanced Rollback Plan< br / > Schema and data rollback] --> H[Data Validation< br / > Verify integrity at each step]
F[Existing IndexedDB Migration] --> G[Enhanced with active_identity support]
H --> I[Platform Testing< br / > Test all platforms]
G --> H[Maintains backward compatibility]
I --> J[Production Deployment< br / > Gradual rollout with monitoring]
H --> I[Preserves existing migration paths]
K[Foreign Key Constraints< br / > Prevent future corruption] --> L[Performance Optimization< br / > Proper indexing]
L --> M[Error Recovery< br / > Graceful failure handling]
```
```
## Interfaces & Contracts
## Current Codebase Assessment
### ✅ What's Already Implemented
### Database Schema Changes
- **Database Schema** : `activeDid` field exists in `settings` table (`src/db-sql/migration.ts:67`)
- **Constants** : `MASTER_SETTINGS_KEY = "1"` is properly defined (`src/db/tables/settings.ts:88`)
- **Types** : Settings type includes `activeDid?: string` (`src/db/tables/settings.ts:25`)
- **Migration Infrastructure** : SQLite migration system exists (`src/db-sql/migration.ts:31`)
- **IndexedDB Migration Service** : Complete service exists (`src/services/indexedDBMigrationService.ts`)
- **PlatformServiceMixin** : Basic structure exists with `$updateActiveDid()` method
| Table | Current Schema | New Schema | Migration Required |
### ❌ What Needs Implementation
|-------|----------------|------------|-------------------|
| `settings` | `activeDid TEXT` | Field removed | Yes - data migration |
| `active_identity` | Does not exist | New table with `activeDid TEXT` + constraints | Yes - table creation |
### Enhanced API Contract Changes
- **Missing Table** : `active_identity` table doesn't exist in current schema
- **Missing API Methods** : Core PlatformServiceMixin methods need implementation
- **Missing Types** : `ActiveIdentity` interface needs creation
| Method | Current Behavior | New Behavior | Breaking Change |
## Required Changes
|---------|------------------|--------------|-----------------|
| `$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 |
## Repro: End-to-End Procedure
### **1. Database Schema via migration.ts**
### Phase 1: Enhanced Schema Creation via migration.ts
Add migration 003 to existing MIGRATIONS array:
```typescript
```typescript
// Add to MIGRATIONS array in src/db-sql/migration.ts
// Add to MIGRATIONS array in src/db-sql/migration.ts
@ -110,88 +103,54 @@ flowchart TD
},
},
```
```
### Phase 2: Enhanced Data Migration with Validation
### **2. Type Definitions**
```typescript
Create ActiveIdentity interface in `src/db/tables/settings.ts` :
// Enhanced migration function with comprehensive validation
async function migrateActiveDidToSeparateTable(): Promise< MigrationResult > {
const result: MigrationResult = {
success: false,
errors: [],
warnings: [],
dataMigrated: 0
};
try {
```typescript
// 1. Get current activeDid from settings (legacy approach)
// Add to src/db/tables/settings.ts
const currentSettings = await retrieveSettingsForDefaultAccount();
export interface ActiveIdentity {
const activeDid = currentSettings.activeDid;
id: number;
activeDid: string;
if (!activeDid) {
lastUpdated: string;
result.warnings.push("No activeDid found in current settings");
return result;
}
}
```
// 2. Validate activeDid exists in accounts table
### **3. PlatformServiceMixin Methods**
const accountExists = await dbQuery(
"SELECT did FROM accounts WHERE did = ?",
[activeDid]
);
if (!accountExists?.values?.length) {
Implement required methods in `src/utils/PlatformServiceMixin.ts` :
result.errors.push(`ActiveDid ${activeDid} not found in accounts table - data corruption detected`);
return result;
}
// 3. Update active_identity table (new system)
```typescript
await dbExec(
// Add to PlatformServiceMixin methods section
"UPDATE active_identity SET activeDid = ?, lastUpdated = datetime('now') WHERE id = 1",
async $getActiveIdentity(): Promise< ActiveIdentity > {
[activeDid]
try {
);
const result = await this.$dbQuery(
"SELECT id, activeDid, lastUpdated FROM active_identity WHERE id = 1"
// 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;
if (result?.values?.length) {
result.warnings.push(`Successfully migrated activeDid: ${activeDid}`);
const [id, activeDid, lastUpdated] = result.values[0];
return { id: id as number, activeDid: activeDid as string, lastUpdated: lastUpdated as string };
}
// Return default if no record exists
return { id: 1, activeDid: '', lastUpdated: new Date().toISOString() };
} catch (error) {
} catch (error) {
result.errors.push(`Migration failed: ${error}`);
logger.error("[PlatformServiceMixin] Error getting active identity:", error );
logger.error("[ActiveDid Migration] Critical error during migration:", error) ;
throw error ;
}
}
return result;
}
}
```
### Phase 3: Focused API Updates with Dual-Write Pattern
```typescript
// Updated PlatformServiceMixin method - maintains backward compatibility
async $accountSettings(did?: string, defaults: Settings = {}): Promise< Settings > {
async $accountSettings(did?: string, defaults: Settings = {}): Promise< Settings > {
try {
try {
// Get settings without activeDid (unchanged logic)
// Get settings without activeDid
const settings = await this._getSettingsWithoutActiveDid( );
const settings = await this.$getSettings(MASTER_SETTINGS_KEY, defaults);
if (!settings) {
if (!settings) {
return defaults;
return defaults;
}
}
// Get activeDid from new table (new logic)
// Get activeDid from new table>
const activeIdentity = await this._getActiveIdentity();
// Return combined result (maintains backward compatibility)
return { ...settings, activeDid: activeIdentity.activeDid };
} catch (error) {
logger.error("[Settings Trace] ❌ Error in $accountSettings:", error);
return defaults;
}
}
// Enhanced update activeDid method with dual-write pattern
// Enhanced update activeDid method with dual-write pattern
async $updateActiveDid(newDid: string | null): Promise< boolean > {
async $updateActiveDid(newDid: string | null): Promise< boolean > {
try {
try {
@ -231,7 +190,7 @@ async $updateActiveDid(newDid: string | null): Promise<boolean> {
);
);
}
}
// Update internal tracking
// Update internal tracking (existing functionality)
await this._updateInternalActiveDid(newDid);
await this._updateInternalActiveDid(newDid);
return true;
return true;
} catch (error) {
} catch (error) {
@ -241,336 +200,107 @@ async $updateActiveDid(newDid: string | null): Promise<boolean> {
}
}
```
```
### **Master Settings Functions Implementation Strategy**
### **4. Integration with Existing IndexedDB Migration Service**
#### **1. Update `retrieveSettingsForDefaultAccount()` **
```typescript
// Enhanced implementation with active_identity table integration
export async function retrieveSettingsForDefaultAccount(): Promise< Settings > {
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);
}
// Get activeDid from separate table
const activeIdentityResult = await platform.dbQuery(
"SELECT activeDid FROM active_identity WHERE id = 1"
);
if (activeIdentityResult?.values?.length) {
The existing `indexedDBMigrationService.ts` already handles activeDid migration
const activeDid = activeIdentityResult.values[0][0] as string;
from Dexie to SQLite. This plan adds the separate table architecture while
if (activeDid) {
maintaining compatibility.
// Validate activeDid exists in accounts
const accountExists = await platform.dbQuery(
"SELECT did FROM accounts WHERE did = ?",
[activeDid]
);
if (accountExists?.values?.length) {
**No changes needed** to the existing migration service - it will continue to
settings.activeDid = activeDid;
work with the dual-write pattern.
} 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"
);
}
}
}
return settings;
## What Doesn't Need to Change
}
}
```
#### **2. Update `$getMergedSettings()` Method**
- **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
- **IndexedDB migration service** - Continues working unchanged
- **Existing database operations** - All current queries continue working
```typescript
## Implementation Steps
// Enhanced implementation with active_identity table integration
async $getMergedSettings(defaultKey: string, accountDid?: string, defaultFallback: Settings = {}): Promise< Settings > {
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"
);
if (activeIdentityResult?.values?.length) {
### **Step 1: Add Migration**
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) {
- Add migration 003 to `MIGRATIONS` array in `src/db-sql/migration.ts`
defaultSettings.activeDid = activeDid;
- Deploy migration to create `active_identity` table
} 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;
}
// ... rest of existing implementation for account-specific settings
### **Step 2: Implement API Methods**
} catch (error) {
logger.error(`[Settings Trace] ❌ Failed to get merged settings:`, { defaultKey, accountDid, error });
return defaultFallback;
}
}
```
## What Works (Evidence)
- Create `ActiveIdentity` interface in `src/db/tables/settings.ts`
- Implement `$getActiveIdentity()` method in PlatformServiceMixin
- Implement `$accountSettings()` method in PlatformServiceMixin
- Enhance `$updateActiveDid()` method with dual-write pattern
- ✅ **Current activeDid storage** in settings table
### **Step 3: Test Integration**
- **Time** : 2025-08-29T08:03Z
- **Evidence** : `src/db-sql/migration.ts:67` - activeDid field exists in initial migration
- **Verify at** : Current database schema and Settings type definition
- ✅ **PlatformServiceMixin integration** with activeDid
- Test new methods with existing components
- **Time** : 2025-08-29T08:03Z
- Verify dual-write pattern works correctly
- **Evidence** : `src/utils/PlatformServiceMixin.ts:108` - activeDid tracking
- Validate backward compatibility
- **Verify at** : Component usage across all platforms
- ✅ **Database migration infrastructure** exists
## Backward Compatibility
- **Time** : 2025-08-29T08:03Z
- **Evidence** : `src/db-sql/migration.ts:31` - migration system in place
- **Verify at** : Existing migration scripts and database versioning
## What Doesn't (Evidence & Hypotheses)
### **Critical Requirements**
- ❌ **No separate active_identity table** exists
- **IndexedDB Migration Service** : Must continue working unchanged
- **Time** : 2025-08-29T08:03Z
- **MASTER_SETTINGS_KEY = "1"** : Must be preserved for legacy support
- **Evidence** : Database schema only shows settings table
- **Dual-Write Pattern** : Ensures both old and new systems stay in sync
- **Hypothesis** : Table needs to be created as part of migration
- **Existing Queries** : All current database operations continue working
- **Next probe** : Add migration to existing MIGRATIONS array
- ❌ **Data corruption issues** with orphaned activeDid references
### **Migration Strategy**
- **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
## Risks, Limits, Assumptions
- **Phase 1** : Add new table alongside existing system
- **Phase 2** : Use dual-write pattern during transition
- **Phase 3** : Future cleanup (not in current scope)
- **Data Loss Risk** : Migration failure could lose activeDid values
## Rollback Strategy
- **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
## Enhanced Rollback Strategy
If migration fails, the existing `activeDid` field in settings table remains functional:
### **Schema Rollback**
```sql
```sql
-- If migration fails, restore original schema
-- Rollback: Remove new table
DROP TABLE IF EXISTS active_identity;
DROP TABLE IF EXISTS active_identity;
-- Restore activeDid field to settings table if needed
ALTER TABLE settings ADD COLUMN activeDid TEXT;
```
```
### **Data Rollback**
No data loss risk - the legacy field continues working unchanged.
```typescript
// Rollback function to restore activeDid to settings table
async function rollbackActiveDidMigration(): Promise< boolean > {
try {
// Get activeDid from active_identity table
const activeIdentityResult = await dbQuery(
"SELECT activeDid FROM active_identity WHERE id = 1"
);
if (activeIdentityResult?.values?.length) {
## Success Criteria
const activeDid = activeIdentityResult.values[0][0] as string;
// Restore to settings table
- [ ] `active_identity` table created with proper constraints
await dbExec(
- [ ] All new PlatformServiceMixin methods implemented and tested
"UPDATE settings SET activeDid = ? WHERE id = ?",
- [ ] Dual-write pattern working correctly
[activeDid, MASTER_SETTINGS_KEY]
- [ ] Existing IndexedDB migration service continues working
);
- [ ] No breaking changes to existing functionality
- [ ] All platforms tested and verified
return true;
}
return false;
} catch (error) {
logger.error("[Rollback] Failed to restore activeDid:", error);
return false;
}
}
```
### **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 |
| QA Team | Platform testing | All platforms tested and verified | 2025-09-01 |
| Development Team | Deploy migration | Production deployment successful | 2025-09-02 |
## 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
## Collaboration Hooks
- **Sign-off checklist** :
- [ ] Migration script integrated with existing MIGRATIONS array
- [ ] Foreign key constraints implemented and tested
- [ ] PlatformServiceMixin updated and tested
- [ ] 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**
## Risks & Mitigation
- 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
### **Low Risk: Migration Failure**
- **All Vue components** - API layer handles migration transparently
- **Mitigation** : Rollback removes new table, legacy system continues working
- **Platform services** - Use PlatformServiceMixin, no direct access
- **Impact** : No data loss, no service interruption
- **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
### **Low Risk: API Changes**
### **Phase 1: Add New Table (Current)**
- **Mitigation** : Dual-write pattern maintains backward compatibility
```typescript
- **Impact** : Existing components continue working unchanged
// Create active_identity table
// Keep existing settings.activeDid for backward compatibility
// Use dual-write pattern during transition
```
### **Phase 2: Dual-Write Pattern**
### **Low Risk: Performance Impact**
```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)**
- **Mitigation** : Proper indexing and minimal additional queries
```typescript
- **Impact** : Negligible performance change
// 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
## Summary
### **Critical: IndexedDB Migration Service**
This migration plan:
- **Must continue working** for users migrating from Dexie
- **Must recognize `id = "1"`** as master settings
- **Must preserve existing migration paths**
### **Important: Legacy Database Operations**
1. **Adds new architecture** without breaking existing functionality
- **Must continue working** for existing SQLite databases
2. **Integrates seamlessly** with existing IndexedDB migration service
- **Must handle both old and new patterns**
3. **Maintains full backward compatibility** during transition
- **Must not break existing queries**
4. **Requires minimal changes** to existing codebase
5. **Provides clear rollback path** if issues arise
### **Desired: Cleaner Architecture**
The plan focuses only on necessary changes while preserving all existing
- **New operations** use `accountDid IS NULL` pattern
functionality and migration paths.
- **Legacy operations** continue using `MASTER_SETTINGS_KEY`
- **Gradual migration** toward cleaner patterns