Reboot of the ActiveDID migration #188

Open
anomalist wants to merge 81 commits from active_did_redux into master
Owner
There is no content yet.
anomalist added 2 commits 3 weeks ago
Poster
Owner

ActiveDid Migration Plan - Separate Table Architecture

Author: Matthew Raymer
Date: 2025-01-27T18:30Z
Status: 🎯 PLANNING - Active migration planning phase

Objective

Move the activeDid field from the settings table to a dedicated
active_identity table to improve database architecture and separate
identity selection from user preferences.

Result

This document serves as the comprehensive planning and implementation
guide for the ActiveDid migration.

Use/Run

Reference this document during implementation to ensure all migration
steps are followed correctly and all stakeholders are aligned on the
approach.

Context & Scope

  • In scope:
    • Database schema modification for active_identity table
    • Migration of existing activeDid data
    • Updates to all platform services and mixins
    • Type definition updates
    • Testing across all platforms
  • Out of scope:
    • Changes to user interface for identity selection
    • Modifications to identity creation logic
    • Changes to authentication flow

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:

flowchart TD
    A[Current State<br/>activeDid in settings] --> B[Phase 1: Schema Creation<br/>Add active_identity table]
    B --> C[Phase 2: Data Migration<br/>Copy activeDid data]
    C --> D[Phase 3: API Updates<br/>Update all access methods]
    D --> E[Phase 4: Cleanup<br/>Remove activeDid from settings]
    E --> F[Final State<br/>Separate active_identity table]

    G[Rollback Plan<br/>Keep old field until verified] --> H[Data Validation<br/>Verify integrity at each step]
    H --> I[Platform Testing<br/>Test all platforms]
    I --> J[Production Deployment<br/>Gradual rollout]

Interfaces & Contracts

Database Schema Changes

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 Yes - table creation

API Contract Changes

Method Current Behavior New Behavior Breaking Change
$accountSettings() Returns settings with activeDid Returns settings without activeDid 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

Repro: End-to-End Procedure

Phase 1: Schema Creation

-- Create new active_identity table
CREATE TABLE active_identity (
  id INTEGER PRIMARY KEY CHECK (id = 1),
  activeDid TEXT NOT NULL,
  lastUpdated TEXT NOT NULL DEFAULT (datetime('now'))
);

-- Insert default record (will be updated during migration)
INSERT INTO active_identity (id, activeDid) VALUES (1, '');

Phase 2: Data Migration

// Migration script to copy existing activeDid values
async function migrateActiveDidToSeparateTable(): Promise<void> {
  // Get current activeDid from settings
  const currentSettings = await retrieveSettingsForDefaultAccount();
  const activeDid = currentSettings.activeDid;

  if (activeDid) {
    // Insert into new table
    await dbExec(
      "UPDATE active_identity SET activeDid = ?, lastUpdated = datetime('now') WHERE id = 1",
      [activeDid]
    );
  }
}

Phase 3: API Updates

// Updated PlatformServiceMixin method
async $accountSettings(did?: string, defaults: Settings = {}): Promise<Settings> {
  // Get settings without activeDid
  const settings = await this._getSettingsWithoutActiveDid();

  // Get activeDid from separate table
  const activeIdentity = await this._getActiveIdentity();

  return { ...settings, activeDid: activeIdentity.activeDid };
}

What Works (Evidence)

  • Current activeDid storage in settings table

    • Time: 2025-01-27T18:30Z
    • Evidence: src/db/tables/settings.ts:25 - activeDid field exists
    • Verify at: Current database schema and Settings type definition
  • PlatformServiceMixin integration with activeDid

    • Time: 2025-01-27T18:30Z
    • Evidence: src/utils/PlatformServiceMixin.ts:108 - activeDid tracking
    • Verify at: Component usage across all platforms
  • Database migration infrastructure exists

    • Time: 2025-01-27T18:30Z
    • Evidence: src/db-sql/migration.ts:31 - migration system in place
    • Verify at: Existing migration scripts and database versioning

What Doesn't (Evidence & Hypotheses)

  • No separate active_identity table exists

    • Time: 2025-01-27T18:30Z
    • Evidence: Database schema only shows settings table
    • Hypothesis: Table needs to be created as part of migration
    • Next probe: Create migration script for new table
  • Platform services hardcoded to settings table

    • Time: 2025-01-27T18:30Z
    • Evidence: src/services/platforms/*.ts - direct settings table access
    • Hypothesis: All platform services need updates
    • Next probe: Audit all platform service files for activeDid usage

Risks, Limits, Assumptions

  • Data Loss Risk: Migration failure could lose activeDid values
  • Breaking Changes: API updates required across all platform services
  • 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

Next Steps

Owner Task Exit Criteria Target Date (UTC)
Development Team Create migration script Migration script tested and validated 2025-01-28
Development Team Update type definitions Settings type updated, ActiveIdentity type created 2025-01-28
Development Team Update platform services All services use new active_identity table 2025-01-29
Development Team Update PlatformServiceMixin Mixin methods updated and tested 2025-01-29
QA Team Platform testing All platforms tested and verified 2025-01-30
Development Team Deploy migration Production deployment successful 2025-01-31

References

Competence Hooks

  • Why this works: Separates concerns between identity selection and
    user preferences, improves database normalization, enables future
    identity management features
  • Common pitfalls: Forgetting to update all platform services, not
    testing rollback scenarios, missing data validation during migration
  • Next skill unlock: Advanced database schema design and migration
    planning
  • Teach-back: Explain the four-phase migration approach and why each
    phase is necessary

Collaboration Hooks

  • Sign-off checklist:
    • Migration script tested on development database
    • All platform services updated and tested
    • Rollback plan 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

Component & View Impact Analysis

High Impact Components

  1. IdentitySection.vue - Direct dependency on activeDid

    • Current: Uses activeDid from component data
    • Impact: Will need to update data binding and refresh logic
    • Risk: HIGH - Core identity display component

    Current Implementation:

    <template>
      <div class="text-sm text-slate-500">
        <div class="font-bold">ID:&nbsp;</div>
        <code class="truncate">{{ activeDid }}</code>
        <!-- ... rest of template -->
      </div>
    </template>
    
    <script lang="ts">
    export default class IdentitySection extends Vue {
      activeDid = ""; // Direct component data
    
      async mounted() {
        const settings = await this.$accountSettings();
        this.activeDid = settings.activeDid || "";
      }
    }
    </script>
    

    Required Changes:

    <script lang="ts">
    export default class IdentitySection extends Vue {
      activeDid = ""; // Still needed for template binding
    
      async mounted() {
        // This will automatically work if $accountSettings() is updated
        const settings = await this.$accountSettings();
        this.activeDid = settings.activeDid || "";
      }
    
      // Add watcher for activeDid changes
      async onActiveDidChanged(newDid: string | null) {
        if (newDid) {
          this.activeDid = newDid;
        }
      }
    }
    </script>
    
  2. DIDView.vue - Heavy activeDid usage

    • Current: Initializes activeDid in mounted() lifecycle
    • Impact: Must update initialization logic to use new table
    • Risk: HIGH - Primary DID viewing component

    Current Implementation:

    <script lang="ts">
    export default class DIDView extends Vue {
      activeDid = ""; // Component data
    
      async mounted() {
        await this.initializeSettings();
        await this.determineDIDToDisplay();
        // ... rest of initialization
      }
    
      private async initializeSettings() {
        const settings = await this.$accountSettings();
        this.activeDid = settings.activeDid || "";
        this.apiServer = settings.apiServer || "";
      }
    
      private async determineDIDToDisplay() {
        const pathParam = window.location.pathname.substring("/did/".length);
        let showDid = pathParam;
    
        if (!showDid) {
          // No DID provided in URL, use active DID
          showDid = this.activeDid; // Uses component data
          this.notifyDefaultToActiveDID();
        }
        // ... rest of logic
      }
    }
    </script>
    

    Required Changes:

    <script lang="ts">
    export default class DIDView extends Vue {
      activeDid = ""; // Component data still needed
    
      async mounted() {
        await this.initializeSettings();
        await this.determineDIDToDisplay();
        // ... rest of initialization
      }
    
      private async initializeSettings() {
        // This will automatically work if $accountSettings() is updated
        const settings = await this.$accountSettings();
        this.activeDid = settings.activeDid || "";
        this.apiServer = settings.apiServer || "";
      }
    
      // Add watcher for activeDid changes
      async onActiveDidChanged(newDid: string | null) {
        if (newDid && newDid !== this.activeDid) {
          this.activeDid = newDid;
          // Re-initialize if needed
          await this.determineDIDToDisplay();
        }
      }
    }
    </script>
    
  3. HomeView.vue - ActiveDid change detection

    • Current: Has onActiveDidChanged() watcher method
    • Impact: Watcher logic needs updates for new data source
    • Risk: MEDIUM - Core navigation component

    Current Implementation:

    <script lang="ts">
    export default class HomeView extends Vue {
      async onActiveDidChanged(newDid: string | null, oldDid: string | null) {
        if (newDid !== oldDid) {
          // Re-initialize identity with new settings (loads settings internally)
          await this.initializeIdentity();
        } else {
          logger.debug(
            "[HomeView Settings Trace] 📍 DID unchanged, skipping re-initialization",
          );
        }
      }
    
      private async initializeIdentity() {
        // ... identity initialization logic
        const settings = await this.$accountSettings();
        this.activeDid = settings.activeDid || "";
        // ... rest of initialization
      }
    }
    </script>
    

    Required Changes:

    <script lang="ts">
    export default class HomeView extends Vue {
      async onActiveDidChanged(newDid: string | null, oldDid: string | null) {
        if (newDid !== oldDid) {
          // This will automatically work if $accountSettings() is updated
          await this.initializeIdentity();
        } else {
          logger.debug(
            "[HomeView Settings Trace] 📍 DID unchanged, skipping re-initialization",
          );
        }
      }
    
      private async initializeIdentity() {
        // ... identity initialization logic
        // This will automatically work if $accountSettings() is updated
        const settings = await this.$accountSettings();
        this.activeDid = settings.activeDid || "";
        // ... rest of initialization
      }
    }
    </script>
    

    Key Insight: HomeView will require minimal changes since it already uses
    the $accountSettings() method, which will be updated to handle the new
    table structure transparently.

Medium Impact Components

  1. InviteOneAcceptView.vue - Identity fallback logic

    • Current: Creates identity if no activeDid exists
    • Impact: Fallback logic needs to check new table
    • Risk: MEDIUM - Invite processing component
  2. ClaimView.vue - Settings retrieval

    • Current: Gets activeDid from $accountSettings()
    • Impact: Will automatically work if API is updated
    • Risk: LOW - Depends on API layer updates
  3. ContactAmountsView.vue - Direct settings access

    • Current: Accesses activeDid directly from settings
    • Impact: Must update to use new API methods
    • Risk: MEDIUM - Financial display component

Service Layer Impact

  1. WebPlatformService.ts

    • Current: Direct SQL queries to settings table
    • Impact: Must add active_identity table queries
    • Risk: HIGH - Core web platform service
  2. CapacitorPlatformService.ts

    • Current: Similar direct SQL access
    • Impact: Same updates as web service
    • Risk: HIGH - Mobile platform service
  3. PlatformServiceMixin.ts

    • Current: Core methods like $accountSettings(), $saveSettings()
    • Impact: Major refactoring required
    • Risk: CRITICAL - Used by 50+ components

API Contract Changes

  1. $saveSettings() method

    • Current: Updates settings.activeDid
    • New: Updates active_identity.activeDid
    • Impact: All components using this method
  2. $updateActiveDid() method

    • Current: Internal tracking only
    • New: Database persistence required
    • Impact: Identity switching logic

Testing Impact

  1. Unit Tests

    • All platform service methods
    • PlatformServiceMixin methods
    • Database migration scripts
  2. Integration Tests

    • Component behavior with new data source
    • Identity switching workflows
    • Settings persistence
  3. Platform Tests

    • Web, Electron, iOS, Android
    • Cross-platform data consistency
    • Migration success on all platforms

Performance Impact

  1. Additional Table Join

    • Settings queries now require active_identity table
    • Potential performance impact on frequent operations
    • Need for proper indexing
  2. Caching Considerations

    • ActiveDid changes trigger cache invalidation
    • Component re-rendering on identity switches
    • Memory usage for additional table data

Risk Assessment by Component Type

  • Critical Risk: PlatformServiceMixin, Platform Services
  • High Risk: Identity-related components, views using $accountSettings()
  • Medium Risk: Components with direct settings access, identity management
  • Low Risk: Components using only basic settings, utility components

Migration Timeline Impact

  • Phase 1: Schema Creation (1-2 days) - No component impact
  • Phase 2: Data Migration (1 day) - No component impact
  • Phase 3: API Updates (3-5 days) - All components affected
  • Phase 4: Cleanup (1-2 days) - No component impact

Update Priority Order

  1. PlatformServiceMixin - Core dependency for most components
  2. Platform Services - Ensure data access layer works
  3. Identity Components - Verify core functionality
  4. Settings-Dependent Views - Update in dependency order
  5. Utility Components - Final cleanup and testing

Deferred for depth

  • Advanced identity management features enabled by this change
  • Performance optimization strategies for the new table structure
  • Future schema evolution planning
  • Advanced rollback and recovery procedures
# ActiveDid Migration Plan - Separate Table Architecture **Author**: Matthew Raymer **Date**: 2025-01-27T18:30Z **Status**: 🎯 **PLANNING** - Active migration planning phase ## Objective Move the `activeDid` field from the `settings` table to a dedicated `active_identity` table to improve database architecture and separate identity selection from user preferences. ## Result This document serves as the comprehensive planning and implementation guide for the ActiveDid migration. ## Use/Run Reference this document during implementation to ensure all migration steps are followed correctly and all stakeholders are aligned on the approach. ## Context & Scope - **In scope**: - Database schema modification for active_identity table - Migration of existing activeDid data - Updates to all platform services and mixins - Type definition updates - Testing across all platforms - **Out of scope**: - Changes to user interface for identity selection - Modifications to identity creation logic - Changes to authentication flow ## 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: ```mermaid flowchart TD A[Current State<br/>activeDid in settings] --> B[Phase 1: Schema Creation<br/>Add active_identity table] B --> C[Phase 2: Data Migration<br/>Copy activeDid data] C --> D[Phase 3: API Updates<br/>Update all access methods] D --> E[Phase 4: Cleanup<br/>Remove activeDid from settings] E --> F[Final State<br/>Separate active_identity table] G[Rollback Plan<br/>Keep old field until verified] --> H[Data Validation<br/>Verify integrity at each step] H --> I[Platform Testing<br/>Test all platforms] I --> J[Production Deployment<br/>Gradual rollout] ``` ## Interfaces & Contracts ### Database Schema Changes | 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` | Yes - table creation | ### API Contract Changes | Method | Current Behavior | New Behavior | Breaking Change | |---------|------------------|--------------|-----------------| | `$accountSettings()` | Returns settings with activeDid | Returns settings without activeDid | 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 | ## Repro: End-to-End Procedure ### Phase 1: Schema Creation ```sql -- Create new active_identity table CREATE TABLE active_identity ( id INTEGER PRIMARY KEY CHECK (id = 1), activeDid TEXT NOT NULL, lastUpdated TEXT NOT NULL DEFAULT (datetime('now')) ); -- Insert default record (will be updated during migration) INSERT INTO active_identity (id, activeDid) VALUES (1, ''); ``` ### Phase 2: Data Migration ```typescript // Migration script to copy existing activeDid values async function migrateActiveDidToSeparateTable(): Promise<void> { // Get current activeDid from settings const currentSettings = await retrieveSettingsForDefaultAccount(); const activeDid = currentSettings.activeDid; if (activeDid) { // Insert into new table await dbExec( "UPDATE active_identity SET activeDid = ?, lastUpdated = datetime('now') WHERE id = 1", [activeDid] ); } } ``` ### Phase 3: API Updates ```typescript // Updated PlatformServiceMixin method async $accountSettings(did?: string, defaults: Settings = {}): Promise<Settings> { // Get settings without activeDid const settings = await this._getSettingsWithoutActiveDid(); // Get activeDid from separate table const activeIdentity = await this._getActiveIdentity(); return { ...settings, activeDid: activeIdentity.activeDid }; } ``` ## What Works (Evidence) - ✅ **Current activeDid storage** in settings table - **Time**: 2025-01-27T18:30Z - **Evidence**: `src/db/tables/settings.ts:25` - activeDid field exists - **Verify at**: Current database schema and Settings type definition - ✅ **PlatformServiceMixin integration** with activeDid - **Time**: 2025-01-27T18:30Z - **Evidence**: `src/utils/PlatformServiceMixin.ts:108` - activeDid tracking - **Verify at**: Component usage across all platforms - ✅ **Database migration infrastructure** exists - **Time**: 2025-01-27T18:30Z - **Evidence**: `src/db-sql/migration.ts:31` - migration system in place - **Verify at**: Existing migration scripts and database versioning ## What Doesn't (Evidence & Hypotheses) - ❌ **No separate active_identity table** exists - **Time**: 2025-01-27T18:30Z - **Evidence**: Database schema only shows settings table - **Hypothesis**: Table needs to be created as part of migration - **Next probe**: Create migration script for new table - ❌ **Platform services hardcoded** to settings table - **Time**: 2025-01-27T18:30Z - **Evidence**: `src/services/platforms/*.ts` - direct settings table access - **Hypothesis**: All platform services need updates - **Next probe**: Audit all platform service files for activeDid usage ## Risks, Limits, Assumptions - **Data Loss Risk**: Migration failure could lose activeDid values - **Breaking Changes**: API updates required across all platform services - **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 ## Next Steps | Owner | Task | Exit Criteria | Target Date (UTC) | |-------|------|---------------|-------------------| | Development Team | Create migration script | Migration script tested and validated | 2025-01-28 | | Development Team | Update type definitions | Settings type updated, ActiveIdentity type created | 2025-01-28 | | Development Team | Update platform services | All services use new active_identity table | 2025-01-29 | | Development Team | Update PlatformServiceMixin | Mixin methods updated and tested | 2025-01-29 | | QA Team | Platform testing | All platforms tested and verified | 2025-01-30 | | Development Team | Deploy migration | Production deployment successful | 2025-01-31 | ## 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, improves database normalization, enables future identity management features - *Common pitfalls*: Forgetting to update all platform services, not testing rollback scenarios, missing data validation during migration - *Next skill unlock*: Advanced database schema design and migration planning - *Teach-back*: Explain the four-phase migration approach and why each phase is necessary ## Collaboration Hooks - **Sign-off checklist**: - [ ] Migration script tested on development database - [ ] All platform services updated and tested - [ ] Rollback plan 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 ## Component & View Impact Analysis ### **High Impact Components** 1. **`IdentitySection.vue`** - Direct dependency on `activeDid` - **Current**: Uses `activeDid` from component data - **Impact**: Will need to update data binding and refresh logic - **Risk**: **HIGH** - Core identity display component **Current Implementation:** ```vue <template> <div class="text-sm text-slate-500"> <div class="font-bold">ID:&nbsp;</div> <code class="truncate">{{ activeDid }}</code> <!-- ... rest of template --> </div> </template> <script lang="ts"> export default class IdentitySection extends Vue { activeDid = ""; // Direct component data async mounted() { const settings = await this.$accountSettings(); this.activeDid = settings.activeDid || ""; } } </script> ``` **Required Changes:** ```vue <script lang="ts"> export default class IdentitySection extends Vue { activeDid = ""; // Still needed for template binding async mounted() { // This will automatically work if $accountSettings() is updated const settings = await this.$accountSettings(); this.activeDid = settings.activeDid || ""; } // Add watcher for activeDid changes async onActiveDidChanged(newDid: string | null) { if (newDid) { this.activeDid = newDid; } } } </script> ``` 2. **`DIDView.vue`** - Heavy activeDid usage - **Current**: Initializes `activeDid` in `mounted()` lifecycle - **Impact**: Must update initialization logic to use new table - **Risk**: **HIGH** - Primary DID viewing component **Current Implementation:** ```vue <script lang="ts"> export default class DIDView extends Vue { activeDid = ""; // Component data async mounted() { await this.initializeSettings(); await this.determineDIDToDisplay(); // ... rest of initialization } private async initializeSettings() { const settings = await this.$accountSettings(); this.activeDid = settings.activeDid || ""; this.apiServer = settings.apiServer || ""; } private async determineDIDToDisplay() { const pathParam = window.location.pathname.substring("/did/".length); let showDid = pathParam; if (!showDid) { // No DID provided in URL, use active DID showDid = this.activeDid; // Uses component data this.notifyDefaultToActiveDID(); } // ... rest of logic } } </script> ``` **Required Changes:** ```vue <script lang="ts"> export default class DIDView extends Vue { activeDid = ""; // Component data still needed async mounted() { await this.initializeSettings(); await this.determineDIDToDisplay(); // ... rest of initialization } private async initializeSettings() { // This will automatically work if $accountSettings() is updated const settings = await this.$accountSettings(); this.activeDid = settings.activeDid || ""; this.apiServer = settings.apiServer || ""; } // Add watcher for activeDid changes async onActiveDidChanged(newDid: string | null) { if (newDid && newDid !== this.activeDid) { this.activeDid = newDid; // Re-initialize if needed await this.determineDIDToDisplay(); } } } </script> ``` 3. **`HomeView.vue`** - ActiveDid change detection - **Current**: Has `onActiveDidChanged()` watcher method - **Impact**: Watcher logic needs updates for new data source - **Risk**: **MEDIUM** - Core navigation component **Current Implementation:** ```vue <script lang="ts"> export default class HomeView extends Vue { async onActiveDidChanged(newDid: string | null, oldDid: string | null) { if (newDid !== oldDid) { // Re-initialize identity with new settings (loads settings internally) await this.initializeIdentity(); } else { logger.debug( "[HomeView Settings Trace] 📍 DID unchanged, skipping re-initialization", ); } } private async initializeIdentity() { // ... identity initialization logic const settings = await this.$accountSettings(); this.activeDid = settings.activeDid || ""; // ... rest of initialization } } </script> ``` **Required Changes:** ```vue <script lang="ts"> export default class HomeView extends Vue { async onActiveDidChanged(newDid: string | null, oldDid: string | null) { if (newDid !== oldDid) { // This will automatically work if $accountSettings() is updated await this.initializeIdentity(); } else { logger.debug( "[HomeView Settings Trace] 📍 DID unchanged, skipping re-initialization", ); } } private async initializeIdentity() { // ... identity initialization logic // This will automatically work if $accountSettings() is updated const settings = await this.$accountSettings(); this.activeDid = settings.activeDid || ""; // ... rest of initialization } } </script> ``` **Key Insight**: HomeView will require minimal changes since it already uses the `$accountSettings()` method, which will be updated to handle the new table structure transparently. ### **Medium Impact Components** 1. **`InviteOneAcceptView.vue`** - Identity fallback logic - **Current**: Creates identity if no `activeDid` exists - **Impact**: Fallback logic needs to check new table - **Risk**: **MEDIUM** - Invite processing component 2. **`ClaimView.vue`** - Settings retrieval - **Current**: Gets `activeDid` from `$accountSettings()` - **Impact**: Will automatically work if API is updated - **Risk**: **LOW** - Depends on API layer updates 3. **`ContactAmountsView.vue`** - Direct settings access - **Current**: Accesses `activeDid` directly from settings - **Impact**: Must update to use new API methods - **Risk**: **MEDIUM** - Financial display component ### **Service Layer Impact** 1. **`WebPlatformService.ts`** - **Current**: Direct SQL queries to settings table - **Impact**: Must add `active_identity` table queries - **Risk**: **HIGH** - Core web platform service 2. **`CapacitorPlatformService.ts`** - **Current**: Similar direct SQL access - **Impact**: Same updates as web service - **Risk**: **HIGH** - Mobile platform service 3. **`PlatformServiceMixin.ts`** - **Current**: Core methods like `$accountSettings()`, `$saveSettings()` - **Impact**: Major refactoring required - **Risk**: **CRITICAL** - Used by 50+ components ### **API Contract Changes** 1. **`$saveSettings()` method** - **Current**: Updates `settings.activeDid` - **New**: Updates `active_identity.activeDid` - **Impact**: All components using this method 2. **`$updateActiveDid()` method** - **Current**: Internal tracking only - **New**: Database persistence required - **Impact**: Identity switching logic ### **Testing Impact** 1. **Unit Tests** - All platform service methods - PlatformServiceMixin methods - Database migration scripts 2. **Integration Tests** - Component behavior with new data source - Identity switching workflows - Settings persistence 3. **Platform Tests** - Web, Electron, iOS, Android - Cross-platform data consistency - Migration success on all platforms ### **Performance Impact** 1. **Additional Table Join** - Settings queries now require active_identity table - Potential performance impact on frequent operations - Need for proper indexing 2. **Caching Considerations** - ActiveDid changes trigger cache invalidation - Component re-rendering on identity switches - Memory usage for additional table data ### **Risk Assessment by Component Type** - **Critical Risk**: PlatformServiceMixin, Platform Services - **High Risk**: Identity-related components, views using `$accountSettings()` - **Medium Risk**: Components with direct settings access, identity management - **Low Risk**: Components using only basic settings, utility components ### **Migration Timeline Impact** - **Phase 1**: Schema Creation (1-2 days) - No component impact - **Phase 2**: Data Migration (1 day) - No component impact - **Phase 3**: API Updates (3-5 days) - All components affected - **Phase 4**: Cleanup (1-2 days) - No component impact ### **Update Priority Order** 1. **PlatformServiceMixin** - Core dependency for most components 2. **Platform Services** - Ensure data access layer works 3. **Identity Components** - Verify core functionality 4. **Settings-Dependent Views** - Update in dependency order 5. **Utility Components** - Final cleanup and testing ## Deferred for depth - Advanced identity management features enabled by this change - Performance optimization strategies for the new table structure - Future schema evolution planning - Advanced rollback and recovery procedures
anomalist added 1 commit 3 weeks ago
anomalist added 1 commit 3 weeks ago
acbc276ef6 docs: enhance activeDid migration plan with implementation details
anomalist added 1 commit 3 weeks ago
anomalist added 1 commit 3 weeks ago
fddb2ac959 feat(migration)!: enhance ActiveDid migration plan with focused implementation
anomalist added 1 commit 3 weeks ago
anomalist added 1 commit 3 weeks ago
1227cdee76 docs(activeDid): streamline migration plan for existing migration service
anomalist added 1 commit 3 weeks ago
95b0cbca78 docs(activeDid): add critical data migration logic to prevent data loss
anomalist added 1 commit 3 weeks ago
4a22a35b3e feat(activeDid): implement migration to separate active_identity table
trentlarson reviewed 2 weeks ago
-- Create new active_identity table with proper constraints
CREATE TABLE IF NOT EXISTS active_identity (
id INTEGER PRIMARY KEY CHECK (id = 1),
activeDid TEXT NOT NULL,
Poster
Owner

Since the activeDid can actually be a blank ('') value, I personally would prefer that this is nullable. (Saying "NOT NULL" but using '' to represent null just feels odd... like something that's trying to bypass type-checking.)

Since the activeDid can actually be a blank ('') value, I personally would prefer that this is nullable. (Saying "NOT NULL" but using '' to represent null just feels odd... like something that's trying to bypass type-checking.)
trentlarson marked this conversation as resolved
trentlarson reviewed 2 weeks ago
);
-- Add performance indexes
CREATE INDEX IF NOT EXISTS idx_active_identity_activeDid ON active_identity(activeDid);
Poster
Owner

Why put an index on activeDid? It'll never be the input to a query.

Why put an index on activeDid? It'll never be the input to a query.
trentlarson marked this conversation as resolved
trentlarson reviewed 2 weeks ago
-- Add performance indexes
CREATE INDEX IF NOT EXISTS idx_active_identity_activeDid ON active_identity(activeDid);
CREATE UNIQUE INDEX IF NOT EXISTS idx_active_identity_single_record ON active_identity(id);
Poster
Owner

There's no reason to index the 'id' column since it's a primary key. (Even if it weren't, we'll only ever have one entry so an index is overkill.)

There's no reason to index the 'id' column since it's a primary key. (Even if it weren't, we'll only ever have one entry so an index is overkill.)
trentlarson marked this conversation as resolved
anomalist added 3 commits 2 weeks ago
a2e6ae5c28 docs(migration): restructure activeDid migration plan for implementation
anomalist added 1 commit 2 weeks ago
18ca6baded docs(migration): update Phase 2 status to COMPLETE with testing notes
anomalist added 2 commits 2 weeks ago
d2e04fe2a0 feat(api)!: fix $getActiveIdentity return type for ActiveDid migration
anomalist added 1 commit 2 weeks ago
eb4ddaba50 feat(migration): complete Step 1 of ActiveDid migration - update () to use new API
anomalist added 1 commit 2 weeks ago
f63f4856bf feat(migration): complete Step 2 of ActiveDid migration - implement dual-write pattern
anomalist added 1 commit 2 weeks ago
b4e1313b22 fix(activeDid): implement dual-write pattern with proper MASTER_SETTINGS_KEY usage
anomalist added 1 commit 2 weeks ago
a522a10fb7 feat(activeDid): complete API layer with minimal safe $accountSettings update
anomalist added 8 commits 2 weeks ago
b374f2e5a1 feat: implement ActiveDid migration to active_identity table
8024688561 docs: document critical Vue reactivity bug and migration progress
2b423b8d7b fix: resolve Playwright test flakiness with robust dialog handling
552de23ef2 refactor: enhance platform service for ActiveDid migration
2db4f8f894 refactor: update components for ActiveDid migration compatibility
aa49a5d8a4 chore: update utilities and configuration for ActiveDid migration
1a5aa7a5ef docs: update development rules and documentation
anomalist added 1 commit 2 weeks ago
anomalist added 31 commits 2 weeks ago
8827c4a973 fix(electron): resolve TypeScript errors in Electron build configuration
f51408e32a feat: add duplicate account import prevention
c4f2bb5e3a refactor: move duplicate account import warnings to notification constants
96e4d3c394 chore - reorder duplication test
40fa38a9ce fix: clean up "register random person" test
e67c97821a fix: change import User Zero function
83c0c18db2 fix: persist identity names per user instead of globally
4a1249d166 feat(electron): add editMenu to enable copy/paste keyboard shortcuts
c9082fa57b refactor: remove single-use notification constant
5f8d1fc8c6 refactor: remove deprecated lastName field from user settings
d339f1a274 chore: remove generated doc
25e37cc415 refactor: consolidate duplicate account checking logic into unified utility
1499211018 refactor: simplify duplicate account error detection
b2536adc4e feat: stabilize Playwright tests after ActiveDid migration
anomalist added 1 commit 2 weeks ago
trentlarson requested changes 2 weeks ago
trentlarson reviewed 2 weeks ago
logger.info("[GiftedDialog] Settings received:", {
activeDid: this.activeDid,
apiServer: this.apiServer,
});
Poster
Owner

I vote we make this a debug.

I vote we make this a debug.
trentlarson marked this conversation as resolved
trentlarson reviewed 2 weeks ago
);
}
},
Poster
Owner

I'm not convinced this is the approach we want for data consistency. If the initial migration goes wrong then we have bigger problems (and hopefully we notify the user).

This will actually pick some other value indiscriminately, and it could do it an unexpected times (eg. in the ContactsView explicitly in this PR, or any other page that accesses the getActiveIdentity). I vote we remove it, and if we feel there are migration problems then provide more feedback for the user to choose.

I'm not convinced this is the approach we want for data consistency. If the initial migration goes wrong then we have bigger problems (and hopefully we notify the user). This will actually pick some other value indiscriminately, and it could do it an unexpected times (eg. in the ContactsView explicitly in this PR, or any other page that accesses the getActiveIdentity). I vote we remove it, and if we feel there are migration problems then provide more feedback for the user to choose.
Poster
Owner

I will have to give this some thought. It did seem to give the whole migration more stability -- but I feel you that it seems a bit "icky"

I will have to give this some thought. It did seem to give the whole migration more stability -- but I feel you that it seems a bit "icky"
Poster
Owner

(Unfortunately the lines have changed, but I assume this is all about the $needsActiveIdentitySelection method.)

I don't see where this is used now. Maybe the usages have been removed, in which case this could be removed. If it's still used or in planning, I'll watch for the usages... I tried to determine the purpose (like why it's good to return true if there is no active identity but there are other settings) but I don't understand.

(Unfortunately the lines have changed, but I assume this is all about the $needsActiveIdentitySelection method.) I don't see where this is used now. Maybe the usages have been removed, in which case this could be removed. If it's still used or in planning, I'll watch for the usages... I tried to determine the purpose (like why it's good to return true if there is no active identity but there are other settings) but I don't understand.
Poster
Owner

$needsActiveIdentitySelection is still there as a definition but it unused. I'm removing it.

$needsActiveIdentitySelection is still there as a definition but it unused. I'm removing it.
Poster
Owner

It's gone! 💥

It's gone! 💥
trentlarson marked this conversation as resolved
Owner

I like the removal of the MASTER_SETTINGS here! 👏 Let's hope it goes well.

I vote we make all those migrations into a single one, since they're all part of the same merge when we go to master.

I like the removal of the MASTER_SETTINGS here! 👏 Let's hope it goes well. I vote we make all those migrations into a single one, since they're all part of the same merge when we go to master.
anomalist added 3 commits 2 weeks ago
3e03aaf1e8 migrate: OfferDialog.vue to use () API
4cb1d8848f migrate: PhotoDialog.vue to use () API
4c761d8fd5 feat(db)!: complete ActiveDid migration to active_identity table
anomalist added 1 commit 2 weeks ago
anomalist added 1 commit 2 weeks ago
10a1f435ed fix(platform): remove auto-fix identity selection and fix feed loading race condition
trentlarson reviewed 2 weeks ago
await this.$dbExec(
"UPDATE active_identity SET activeDid = '', lastUpdated = datetime('now') WHERE id = 1",
);
return { activeDid: "" };
Poster
Owner

I'm still not sure that these checks are necessary but I won't let that hold up things since I don't see how it can hurt. But: instead of erasing the activeDid, I suggest we keep the value and create a blank entry for it in the settings table.

I'm still not sure that these checks are necessary but I won't let that hold up things since I don't see how it can hurt. But: instead of erasing the activeDid, I suggest we keep the value and create a blank entry for it in the settings table.
Poster
Owner

I tweaked this a bit but the checks are still there. I've got it wired up to a foreign key (accounts.did).

I'll try a bit of a clean-up experiment.

I tweaked this a bit but the checks are still there. I've got it wired up to a foreign key (accounts.did). I'll try a bit of a clean-up experiment.
Poster
Owner

Looks good to me.

Looks good to me.
trentlarson marked this conversation as resolved
trentlarson reviewed 2 weeks ago
// eslint-disable-next-line @typescript-eslint/no-unused-vars
void id;
// eslint-disable-next-line @typescript-eslint/no-unused-vars
void activeDidField;
Poster
Owner

These voids seem unnecessary. Educate me if I'm wrong.

These voids seem unnecessary. Educate me if I'm wrong.
Poster
Owner

Really depends on your philosophy of typing. I vote they stay since they only make it explicit and don't survive into the actual build.

Really depends on your philosophy of typing. I vote they stay since they only make it explicit and don't survive into the actual build.
trentlarson marked this conversation as resolved
trentlarson reviewed 2 weeks ago
trentlarson reviewed 2 weeks ago
elementWillRender:
this.numNewOffersToUser + this.numNewOffersToUserProjects > 0,
timestamp: new Date().toISOString(),
});
Poster
Owner

More logging that seems like they should be "debug" statements.

More logging that seems like they should be "debug" statements.
Poster
Owner

I'll be doing another pass on these before we merge into master.

I'll be doing another pass on these before we merge into master.
trentlarson marked this conversation as resolved
trentlarson reviewed 2 weeks ago
return true;
}
return false;
}, { timeout: 5000 });
Poster
Owner

If these timeout, do the tests fail? (I hope so. The Playwright docs don't make it obvious.)

If these timeout, do the tests fail? (I hope so. The Playwright docs don't make it obvious.)
Poster
Owner

If I remember correctly (and pretty sure I do), there is a global timeout of 45s so "yes".

If I remember correctly (and pretty sure I do), there is a global timeout of 45s so "yes".
Poster
Owner

Updated. Internal documentation to spell this out for you.

Updated. Internal documentation to spell this out for you.
trentlarson marked this conversation as resolved
trentlarson reviewed 2 weeks ago
if (process.env.NODE_ENV === 'development') {
process.env.VITE_DEFAULT_ENDORSER_API_SERVER = 'http://localhost:3000';
process.env.VITE_DEFAULT_PARTNER_API_SERVER = 'http://localhost:3000';
}
Poster
Owner

If this is necessary then it appears that something is wrong with the ".env.development" environment loading on line 9. Is there something deeper to fix here? (I ask because it's the addition of more environment logic, where it would be preferable to keep these forced settings isolated for maintainability.)

If this is necessary then it appears that something is wrong with the ".env.development" environment loading on line 9. Is there something deeper to fix here? (I ask because it's the addition of more environment logic, where it would be preferable to keep these forced settings isolated for maintainability.)
Poster
Owner

Yeah I saw this as well. I'll clean this up today.

Yeah I saw this as well. I'll clean this up today.
trentlarson marked this conversation as resolved
anomalist added 2 commits 2 weeks ago
b57be7670c refactor: improve logging levels and environment configuration
anomalist added 1 commit 2 weeks ago
704e495f5d refactor(db): consolidate database migrations from 6 to 3
jose added 1 commit 2 weeks ago
578dbe6177 fix: simplify active_identity migration to resolve iOS SQLite failures
jose added 1 commit 2 weeks ago
448d8a68d2 fix: improve code formatting in migrationService.ts
trentlarson added 1 commit 1 week ago
trentlarson added 1 commit 1 week ago
anomalist added 1 commit 1 week ago
a20c321a16 feat: implement Active Pointer + Smart Deletion Pattern for accounts
anomalist added 1 commit 1 week ago
anomalist added 2 commits 1 week ago
d9569922eb docs: merge notification system docs into single Native-First guide
anomalist added 1 commit 1 week ago
ccb1f29df4 fix: improve type safety and fix Playwright test dialog handling
anomalist added 2 commits 1 week ago
e1cf27be05 refactor(db): restructure migrations to preserve master compatibility
anomalist added 1 commit 1 week ago
d6b5e13499 fix(tests): resolve dialog button selector issues in Playwright tests
anomalist added 1 commit 1 week ago
79cb52419e fix(tests): improve Playwright test reliability with robust onboarding and timing fixes
jose added 1 commit 1 week ago
7b40012df4 fix: implement missing $getAllAccountDids method in PlatformServiceMixin
jose added 1 commit 1 week ago
6fb4ceab81 fix(playwright): re-route after affirming onboarding dialog
trentlarson added 1 commit 6 days ago
trentlarson added 1 commit 6 days ago
anomalist added 2 commits 6 days ago
b06e2b46f6 feat: migrate TopMessage.vue to use new ActiveDid pattern
anomalist added 1 commit 5 days ago
e856ace61f feat: migrate DiscoverView.vue to use new ActiveDid pattern
anomalist added 1 commit 5 days ago
6da9e14b8a feat: complete ActiveDid migration for remaining Vue components
anomalist added 2 commits 5 days ago
616bef655a fix: Resolve database migration issues and consolidate 003 migrations
anomalist added 3 commits 5 days ago
8eb4ad5c74 refactor: Remove defunct $needsActiveIdentitySelection method and fix activeDid consistency
cf854d5054 refactor: clean up $getActiveIdentity method and fix null handling
anomalist added 1 commit 5 days ago
jose added 1 commit 5 days ago
7917e707e9 fix: resolve iOS database migration failure for active_identity table
anomalist added 1 commit 5 days ago
31f66909fa refactor: implement team feedback for active identity migration structure
anomalist added 1 commit 4 days ago
anomalist added 1 commit 4 days ago
trentlarson added 1 commit 1 day ago
trentlarson added 1 commit 1 day ago
anomalist added 2 commits 1 day ago
8b8566c578 fix: resolve build errors and test timing issues
anomalist added 1 commit 1 day ago
d01c6c2e9b feat: implement Migration 005 - fix foreign key constraint to ON DELETE RESTRICT
anomalist added 1 commit 1 day ago
0ca70b0f4e feat: complete Active Pointer + Smart Deletion Pattern implementation
anomalist added 1 commit 22 hours ago
anomalist added 1 commit 5 hours ago
24ec81b0ba refactor: consolidate active identity migrations 004-006 into single migration
anomalist added 1 commit 4 minutes ago
anomalist added 1 commit 3 minutes ago

Reviewers

trentlarson requested changes 2 weeks ago
This pull request can be merged automatically.
You are not authorized to merge this pull request.
Sign in to join this conversation.
No reviewers
No Label
No Milestone
No Assignees
3 Participants
Notifications
Due Date

No due date set.

Dependencies

This pull request currently doesn't have any dependencies.

Loading…
There is no content yet.