feat(db): implement active identity table separation #180

Open
anomalist wants to merge 1 commits from activedid_migration into master
Owner

Active Identity Implementation Overview

Author: Matthew Raymer
Date: 2025-08-21T13:40Z
Status: 🚧 IN PROGRESS - Implementation Complete, Testing Pending

Objective

Separate the activeDid field from the monolithic settings table into a
dedicated active_identity table to achieve:

  • Data normalization and reduced cache drift
  • Simplified identity management with dedicated table
  • Zero breaking API surface for existing components
  • Phased migration with rollback capability

Result

This document provides a comprehensive overview of the implemented Active
Identity table separation system, including architecture, migration strategy,
and component integration.

Use/Run

The implementation is ready for testing. Components can immediately use the new
façade methods while maintaining backward compatibility through dual-write
triggers.

Context & Scope

  • Audience: Developers working with identity management and database
    migrations
  • In scope: Active DID management, database schema evolution, Vue component
    integration
  • Out of scope: Multi-profile support beyond basic scope framework, complex
    identity hierarchies
  • Implementation: src/db/tables/activeIdentity.ts,
    src/utils/PlatformServiceMixin.ts
  • Migrations: src/db-sql/migration.ts (migrations 003 & 004)
  • Configuration: src/config/featureFlags.ts
  • Documentation: This document and progress tracking

Environment & Preconditions

  • Database: SQLite (Absurd-SQL for Web, Capacitor SQLite for Mobile)
  • Framework: Vue.js with PlatformServiceMixin
  • Migration System: Built-in migrationService.ts with automatic execution

Architecture / Process Overview

The Active Identity separation follows a phased migration pattern with
dual-write triggers to ensure zero downtime and backward compatibility.

flowchart TD
    A[Legacy State] --> B[Phase A: Dual-Write]
    B --> C[Phase B: Component Cutover]
    C --> D[Phase C: Legacy Cleanup]

    A --> A1[settings.activeDid]
    B --> B1[active_identity table]
    B --> B2[Dual-write trigger]
    B --> B3[Fallback support]
    C --> C1[Components use façade]
    C --> C2[Legacy fallback disabled]
    D --> D1[Drop activeDid column]
    D --> D2[Remove triggers]

Interfaces & Contracts

Database Schema

Table Purpose Key Fields Constraints
active_identity Store active DID per scope scope, active_did, Unique scope, FK to accounts.did
updated_at
settings User preferences (legacy) id, accountDid, apiServer, activeDid removed in Phase C
etc.

Service Façade API

Method Purpose Parameters Returns
$getActiveDid(scope?) Retrieve active DID scope (default: 'default') Promise<string | null>
$setActiveDid(did, scope?) Set active DID did, scope (default: Promise<void>
'default')
$switchActiveIdentity(did) Switch to different DID did Promise<void>
$getActiveIdentityScopes() Get available scopes None Promise<string[]>

Repro: End-to-End Procedure

1. Database Migration Execution

# Migrations run automatically on app startup
# Migration 003: Creates active_identity table
# Migration 004: Drops settings.activeDid column (Phase C)

2. Component Usage

// Before (legacy)
const activeDid = settings.activeDid || "";
await this.$saveSettings({ activeDid: newDid });

// After (new façade)
const activeDid = await this.$getActiveDid() || "";
await this.$setActiveDid(newDid);

3. Feature Flag Control

// Enable/disable migration phases
FLAGS.USE_ACTIVE_IDENTITY_ONLY = false;      // Allow legacy fallback
FLAGS.DROP_SETTINGS_ACTIVEDID = false;       // Keep legacy column
FLAGS.LOG_ACTIVE_ID_FALLBACK = true;         // Log fallback usage

What Works (Evidence)

  • Migration Infrastructure: Migrations 003 and 004 integrated into
    migrationService.ts
  • Table Creation: active_identity table schema with proper constraints
    and indexes
  • Service Façade: PlatformServiceMixin extended with all required methods
  • Feature Flags: Comprehensive flag system for controlling rollout phases
  • Dual-Write Support: One-way trigger from settings.activeDid
    active_identity.active_did
  • Validation: DID existence validation before setting as active
  • Error Handling: Comprehensive error handling with logging

What Doesn't (Evidence & Hypotheses)

  • Component Migration: No components yet updated to use new façade
    methods
  • Testing: No automated tests for new functionality
  • Performance Validation: No benchmarks for read/write performance
  • Cross-Platform Validation: Not tested on mobile platforms yet

Risks, Limits, Assumptions

Migration Risks

  • Data Loss: If migration fails mid-process, could lose active DID state
  • Rollback Complexity: Phase C (column drop) requires table rebuild, not
    easily reversible
  • Trigger Dependencies: Dual-write trigger could fail if active_identity
    table is corrupted

Performance Limits

  • Dual-Write Overhead: Each activeDid change triggers additional
    database operations
  • Fallback Queries: Legacy fallback requires additional database queries
  • Transaction Scope: Active DID changes wrapped in transactions for
    consistency

Security Boundaries

  • DID Validation: Only validates DID exists in accounts table, not
    ownership
  • Scope Isolation: No current scope separation enforcement beyond table
    constraints
  • Access Control: No row-level security on active_identity table

Next Steps

Owner Task Exit Criteria Target Date (UTC)
Developer Test migrations Migrations execute without errors 2025-08-21
Developer Update components All components use new façade methods 2025-08-22
Developer Performance testing Read/write performance meets requirements 2025-08-23
Developer Phase C activation Feature flag enables column removal 2025-08-24

References

Competence Hooks

  • Why this works: Phased migration with dual-write triggers ensures zero
    downtime while maintaining data consistency through foreign key constraints
    and validation
  • Common pitfalls: Forgetting to update components before enabling
    USE_ACTIVE_IDENTITY_ONLY, not testing rollback scenarios, ignoring
    cross-platform compatibility
  • Next skill unlock: Implement automated component migration using codemods
    and ESLint rules
  • Teach-back: Explain how the dual-write trigger prevents data divergence
    during the transition phase

Collaboration Hooks

  • Reviewers: Database team for migration logic, Vue team for component
    integration, DevOps for deployment strategy
  • Sign-off checklist: Migrations tested in staging, components updated,
    performance validated, rollback plan documented

Assumptions & Limits

  • Single User Focus: Current implementation assumes single-user mode with
    'default' scope
  • Vue Compatibility: Assumes vue-facing-decorator compatibility (needs
    validation)
  • Migration Timing: Assumes migrations run on app startup (automatic
    execution)
  • Platform Support: Assumes same behavior across Web (Absurd-SQL) and
    Mobile (Capacitor SQLite)

Implementation Details

Migration 003: Table Creation

Creates the active_identity table with:

  • Primary Key: Auto-incrementing ID
  • Scope Field: For future multi-profile support (currently 'default')
  • Active DID: Foreign key to accounts.did with CASCADE UPDATE
  • Timestamps: ISO format timestamps for audit trail
  • Indexes: Performance optimization for scope and DID lookups

Migration 004: Column Removal

Implements Phase C by:

  • Table Rebuild: Creates new settings table without activeDid column
  • Data Preservation: Copies all other data from legacy table
  • Index Recreation: Rebuilds necessary indexes
  • Trigger Cleanup: Removes dual-write triggers

Service Façade Implementation

The PlatformServiceMixin extension provides:

  • Dual-Read Logic: Prefers new table, falls back to legacy during
    transition
  • Dual-Write Logic: Updates both tables during Phase A/B
  • Validation: Ensures DID exists before setting as active
  • Transaction Safety: Wraps operations in database transactions
  • Error Handling: Comprehensive logging and error propagation

Feature Flag System

Controls migration phases through:

  • USE_ACTIVE_IDENTITY_ONLY: Disables legacy fallback reads
  • DROP_SETTINGS_ACTIVEDID: Enables Phase C column removal
  • LOG_ACTIVE_ID_FALLBACK: Logs when legacy fallback is used
  • ENABLE_ACTIVE_IDENTITY_MIGRATION: Master switch for migration
    system

Security Considerations

Data Validation

  • DID format validation (basic "did:" prefix check)
  • Foreign key constraints ensure referential integrity
  • Transaction wrapping prevents partial updates

Access Control

  • No row-level security implemented
  • Scope isolation framework in place for future use
  • Validation prevents setting non-existent DIDs as active

Audit Trail

  • Timestamps on all active identity changes
  • Logging of fallback usage and errors
  • Migration tracking through built-in system

Performance Characteristics

Read Operations

  • Primary Path: Single query to active_identity table
  • Fallback Path: Additional query to settings table (Phase A only)
  • Indexed Fields: Both scope and active_did are indexed

Write Operations

  • Dual-Write: Updates both tables during transition (Phase A/B)
  • Transaction Overhead: All operations wrapped in transactions
  • Trigger Execution: Additional database operations per update

Migration Impact

  • Table Creation: Minimal impact (runs once)
  • Column Removal: Moderate impact (table rebuild required)
  • Data Seeding: Depends on existing data volume

Testing Strategy

Unit Testing

  • Service façade method validation
  • Error handling and edge cases
  • Transaction rollback scenarios

Integration Testing

  • Migration execution and rollback
  • Cross-platform compatibility
  • Performance under load

End-to-End Testing

  • Component integration
  • User workflow validation
  • Migration scenarios

Deployment Considerations

Rollout Strategy

  • Phase A: Deploy with dual-write enabled
  • Phase B: Update components to use new methods
  • Phase C: Enable column removal (irreversible)

Rollback Plan

  • Phase A/B: Disable feature flags, revert to legacy methods
  • Phase C: Requires database restore (no automatic rollback)

Monitoring

  • Track fallback usage through logging
  • Monitor migration success rates
  • Alert on validation failures

Status: Implementation complete, ready for testing and component migration
Next Review: After initial testing and component updates
Maintainer: Development team

# Active Identity Implementation Overview **Author**: Matthew Raymer **Date**: 2025-08-21T13:40Z **Status**: 🚧 **IN PROGRESS** - Implementation Complete, Testing Pending ## Objective Separate the `activeDid` field from the monolithic `settings` table into a dedicated `active_identity` table to achieve: - **Data normalization** and reduced cache drift - **Simplified identity management** with dedicated table - **Zero breaking API surface** for existing components - **Phased migration** with rollback capability ## Result This document provides a comprehensive overview of the implemented Active Identity table separation system, including architecture, migration strategy, and component integration. ## Use/Run The implementation is ready for testing. Components can immediately use the new façade methods while maintaining backward compatibility through dual-write triggers. ## Context & Scope - **Audience**: Developers working with identity management and database migrations - **In scope**: Active DID management, database schema evolution, Vue component integration - **Out of scope**: Multi-profile support beyond basic scope framework, complex identity hierarchies ## Artifacts & Links - **Implementation**: `src/db/tables/activeIdentity.ts`, `src/utils/PlatformServiceMixin.ts` - **Migrations**: `src/db-sql/migration.ts` (migrations 003 & 004) - **Configuration**: `src/config/featureFlags.ts` - **Documentation**: This document and progress tracking ## Environment & Preconditions - **Database**: SQLite (Absurd-SQL for Web, Capacitor SQLite for Mobile) - **Framework**: Vue.js with PlatformServiceMixin - **Migration System**: Built-in migrationService.ts with automatic execution ## Architecture / Process Overview The Active Identity separation follows a **phased migration pattern** with dual-write triggers to ensure zero downtime and backward compatibility. ```mermaid flowchart TD A[Legacy State] --> B[Phase A: Dual-Write] B --> C[Phase B: Component Cutover] C --> D[Phase C: Legacy Cleanup] A --> A1[settings.activeDid] B --> B1[active_identity table] B --> B2[Dual-write trigger] B --> B3[Fallback support] C --> C1[Components use façade] C --> C2[Legacy fallback disabled] D --> D1[Drop activeDid column] D --> D2[Remove triggers] ``` ## Interfaces & Contracts ### Database Schema | Table | Purpose | Key Fields | Constraints | |-------|---------|------------|-------------| | `active_identity` | Store active DID per scope | `scope`, `active_did`, | Unique scope, FK to accounts.did | | | | `updated_at` | | | `settings` | User preferences (legacy) | `id`, `accountDid`, `apiServer`, | `activeDid` removed in Phase C | | | | etc. | | ### Service Façade API | Method | Purpose | Parameters | Returns | |--------|---------|------------|---------| | `$getActiveDid(scope?)` | Retrieve active DID | `scope` (default: 'default') | `Promise<string \| null>` | | `$setActiveDid(did, scope?)` | Set active DID | `did`, `scope` (default: | `Promise<void>` | | | | 'default') | | | `$switchActiveIdentity(did)` | Switch to different DID | `did` | `Promise<void>` | | `$getActiveIdentityScopes()` | Get available scopes | None | `Promise<string[]>` | ## Repro: End-to-End Procedure ### 1. Database Migration Execution ```bash # Migrations run automatically on app startup # Migration 003: Creates active_identity table # Migration 004: Drops settings.activeDid column (Phase C) ``` ### 2. Component Usage ```typescript // Before (legacy) const activeDid = settings.activeDid || ""; await this.$saveSettings({ activeDid: newDid }); // After (new façade) const activeDid = await this.$getActiveDid() || ""; await this.$setActiveDid(newDid); ``` ### 3. Feature Flag Control ```typescript // Enable/disable migration phases FLAGS.USE_ACTIVE_IDENTITY_ONLY = false; // Allow legacy fallback FLAGS.DROP_SETTINGS_ACTIVEDID = false; // Keep legacy column FLAGS.LOG_ACTIVE_ID_FALLBACK = true; // Log fallback usage ``` ## What Works (Evidence) - ✅ **Migration Infrastructure**: Migrations 003 and 004 integrated into `migrationService.ts` - ✅ **Table Creation**: `active_identity` table schema with proper constraints and indexes - ✅ **Service Façade**: PlatformServiceMixin extended with all required methods - ✅ **Feature Flags**: Comprehensive flag system for controlling rollout phases - ✅ **Dual-Write Support**: One-way trigger from `settings.activeDid` → `active_identity.active_did` - ✅ **Validation**: DID existence validation before setting as active - ✅ **Error Handling**: Comprehensive error handling with logging ## What Doesn't (Evidence & Hypotheses) - ❌ **Component Migration**: No components yet updated to use new façade methods - ❌ **Testing**: No automated tests for new functionality - ❌ **Performance Validation**: No benchmarks for read/write performance - ❌ **Cross-Platform Validation**: Not tested on mobile platforms yet ## Risks, Limits, Assumptions ### **Migration Risks** - **Data Loss**: If migration fails mid-process, could lose active DID state - **Rollback Complexity**: Phase C (column drop) requires table rebuild, not easily reversible - **Trigger Dependencies**: Dual-write trigger could fail if `active_identity` table is corrupted ### **Performance Limits** - **Dual-Write Overhead**: Each `activeDid` change triggers additional database operations - **Fallback Queries**: Legacy fallback requires additional database queries - **Transaction Scope**: Active DID changes wrapped in transactions for consistency ### **Security Boundaries** - **DID Validation**: Only validates DID exists in accounts table, not ownership - **Scope Isolation**: No current scope separation enforcement beyond table constraints - **Access Control**: No row-level security on `active_identity` table ## Next Steps | Owner | Task | Exit Criteria | Target Date (UTC) | |-------|------|---------------|-------------------| | Developer | Test migrations | Migrations execute without errors | 2025-08-21 | | Developer | Update components | All components use new façade methods | 2025-08-22 | | Developer | Performance testing | Read/write performance meets requirements | 2025-08-23 | | Developer | Phase C activation | Feature flag enables column removal | 2025-08-24 | ## References - [Database Migration Guide](../database-migration-guide.md) - [PlatformServiceMixin Documentation](../component-communication-guide.md) - [Feature Flags Configuration](../feature-flags.md) ## Competence Hooks - **Why this works**: Phased migration with dual-write triggers ensures zero downtime while maintaining data consistency through foreign key constraints and validation - **Common pitfalls**: Forgetting to update components before enabling `USE_ACTIVE_IDENTITY_ONLY`, not testing rollback scenarios, ignoring cross-platform compatibility - **Next skill unlock**: Implement automated component migration using codemods and ESLint rules - **Teach-back**: Explain how the dual-write trigger prevents data divergence during the transition phase ## Collaboration Hooks - **Reviewers**: Database team for migration logic, Vue team for component integration, DevOps for deployment strategy - **Sign-off checklist**: Migrations tested in staging, components updated, performance validated, rollback plan documented ## Assumptions & Limits - **Single User Focus**: Current implementation assumes single-user mode with 'default' scope - **Vue Compatibility**: Assumes `vue-facing-decorator` compatibility (needs validation) - **Migration Timing**: Assumes migrations run on app startup (automatic execution) - **Platform Support**: Assumes same behavior across Web (Absurd-SQL) and Mobile (Capacitor SQLite) ## Implementation Details ### **Migration 003: Table Creation** Creates the `active_identity` table with: - **Primary Key**: Auto-incrementing ID - **Scope Field**: For future multi-profile support (currently 'default') - **Active DID**: Foreign key to accounts.did with CASCADE UPDATE - **Timestamps**: ISO format timestamps for audit trail - **Indexes**: Performance optimization for scope and DID lookups ### **Migration 004: Column Removal** Implements Phase C by: - **Table Rebuild**: Creates new settings table without activeDid column - **Data Preservation**: Copies all other data from legacy table - **Index Recreation**: Rebuilds necessary indexes - **Trigger Cleanup**: Removes dual-write triggers ### **Service Façade Implementation** The PlatformServiceMixin extension provides: - **Dual-Read Logic**: Prefers new table, falls back to legacy during transition - **Dual-Write Logic**: Updates both tables during Phase A/B - **Validation**: Ensures DID exists before setting as active - **Transaction Safety**: Wraps operations in database transactions - **Error Handling**: Comprehensive logging and error propagation ### **Feature Flag System** Controls migration phases through: - **`USE_ACTIVE_IDENTITY_ONLY`**: Disables legacy fallback reads - **`DROP_SETTINGS_ACTIVEDID`**: Enables Phase C column removal - **`LOG_ACTIVE_ID_FALLBACK`**: Logs when legacy fallback is used - **`ENABLE_ACTIVE_IDENTITY_MIGRATION`**: Master switch for migration system ## Security Considerations ### **Data Validation** - DID format validation (basic "did:" prefix check) - Foreign key constraints ensure referential integrity - Transaction wrapping prevents partial updates ### **Access Control** - No row-level security implemented - Scope isolation framework in place for future use - Validation prevents setting non-existent DIDs as active ### **Audit Trail** - Timestamps on all active identity changes - Logging of fallback usage and errors - Migration tracking through built-in system ## Performance Characteristics ### **Read Operations** - **Primary Path**: Single query to `active_identity` table - **Fallback Path**: Additional query to `settings` table (Phase A only) - **Indexed Fields**: Both scope and active_did are indexed ### **Write Operations** - **Dual-Write**: Updates both tables during transition (Phase A/B) - **Transaction Overhead**: All operations wrapped in transactions - **Trigger Execution**: Additional database operations per update ### **Migration Impact** - **Table Creation**: Minimal impact (runs once) - **Column Removal**: Moderate impact (table rebuild required) - **Data Seeding**: Depends on existing data volume ## Testing Strategy ### **Unit Testing** - Service façade method validation - Error handling and edge cases - Transaction rollback scenarios ### **Integration Testing** - Migration execution and rollback - Cross-platform compatibility - Performance under load ### **End-to-End Testing** - Component integration - User workflow validation - Migration scenarios ## Deployment Considerations ### **Rollout Strategy** - **Phase A**: Deploy with dual-write enabled - **Phase B**: Update components to use new methods - **Phase C**: Enable column removal (irreversible) ### **Rollback Plan** - **Phase A/B**: Disable feature flags, revert to legacy methods - **Phase C**: Requires database restore (no automatic rollback) ### **Monitoring** - Track fallback usage through logging - Monitor migration success rates - Alert on validation failures --- **Status**: Implementation complete, ready for testing and component migration **Next Review**: After initial testing and component updates **Maintainer**: Development team
anomalist added 1 commit 6 hours ago
b2e678dc2f feat(db): implement active identity table separation
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
1 Participants
Notifications
Due Date

No due date set.

Dependencies

This pull request currently doesn't have any dependencies.

Loading…
There is no content yet.