11 KiB
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.
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 | id , active_did , |
FK to accounts.did |
updated_at |
Service Façade API
Method | Purpose | Parameters | Returns |
---|---|---|---|
$getActiveDid() |
Retrieve active DID | None | Promise<string | null> |
$setActiveDid(did) |
Set active DID | did |
Promise<void> |
$switchActiveIdentity(did) |
Switch to different DID | did |
Promise<void> |
$getActiveIdentityScopes() |
Get available scopes | None | Promise<string[]> (always returns ["default"] ) |
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 | 2025-08-22 |
methods | |||
Developer | Performance testing | Read/write performance meets | 2025-08-23 |
requirements | |||
Developer | Phase C activation | Feature flag enables column | 2025-08-24 |
removal |
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 readsDROP_SETTINGS_ACTIVEDID
: Enables Phase C column removalLOG_ACTIVE_ID_FALLBACK
: Logs when legacy fallback is usedENABLE_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