1 changed files with 510 additions and 0 deletions
@ -0,0 +1,510 @@ |
|||||
|
# Active Identity Migration & Upgrade (Merged) |
||||
|
|
||||
|
## Part 1: Database Migration Impact Analysis |
||||
|
|
||||
|
# Database Migration Impact Analysis |
||||
|
|
||||
|
## Current State Analysis |
||||
|
|
||||
|
### Existing Migration Structure |
||||
|
The current migration system has: |
||||
|
- **Migration 003**: `003_active_identity_and_seed_backup` - Creates `active_identity` table with basic structure |
||||
|
- **Foreign Key**: `ON DELETE SET NULL` constraint |
||||
|
- **Basic Indexing**: Single unique index on `id` |
||||
|
- **Bootstrapping**: Auto-selects first account if `activeDid` is null/empty |
||||
|
|
||||
|
### Current Schema (Migration 003) |
||||
|
```sql |
||||
|
CREATE TABLE IF NOT EXISTS active_identity ( |
||||
|
id INTEGER PRIMARY KEY CHECK (id = 1), |
||||
|
activeDid TEXT DEFAULT NULL, |
||||
|
lastUpdated TEXT NOT NULL DEFAULT (datetime('now')), |
||||
|
FOREIGN KEY (activeDid) REFERENCES accounts(did) ON DELETE SET NULL |
||||
|
); |
||||
|
``` |
||||
|
|
||||
|
## Proposed Changes Impact |
||||
|
|
||||
|
### 1. Foreign Key Constraint Change |
||||
|
**Current**: `ON DELETE SET NULL` |
||||
|
**Proposed**: `ON DELETE RESTRICT` |
||||
|
|
||||
|
**Impact**: |
||||
|
- **Data Safety**: Prevents accidental deletion of active account |
||||
|
- **Migration Rewrite**: Update existing migration 003 |
||||
|
|
||||
|
### 2. Automatic Timestamp Updates |
||||
|
**Current**: Manual `lastUpdated` updates in code |
||||
|
**Proposed**: Database trigger for automatic updates |
||||
|
|
||||
|
**Impact**: |
||||
|
- **Code Simplification**: Remove manual timestamp updates from `PlatformServiceMixin` |
||||
|
- **Consistency**: Ensures `lastUpdated` is always current |
||||
|
|
||||
|
### 3. Enhanced Indexing |
||||
|
**Current**: Single unique index on `id` |
||||
|
**Proposed**: Additional index on `accounts(dateCreated, did)` |
||||
|
|
||||
|
**Impact**: |
||||
|
- **Performance Improvement**: Faster account selection queries |
||||
|
- **Minimal Risk**: Additive change only |
||||
|
|
||||
|
## Implementation Strategy |
||||
|
|
||||
|
### Rewrite Migration 003 |
||||
|
Since the `active_identity` table is new and we're in active development, we can simply rewrite the existing migration: |
||||
|
|
||||
|
```sql |
||||
|
{ |
||||
|
name: "003_active_identity_and_seed_backup", |
||||
|
sql: ` |
||||
|
-- Enable foreign key constraints for data integrity |
||||
|
PRAGMA foreign_keys = ON; |
||||
|
|
||||
|
-- Add UNIQUE constraint to accounts.did for foreign key support |
||||
|
CREATE UNIQUE INDEX IF NOT EXISTS idx_accounts_did_unique ON accounts(did); |
||||
|
|
||||
|
-- Create active_identity table with enhanced constraints |
||||
|
CREATE TABLE IF NOT EXISTS active_identity ( |
||||
|
id INTEGER PRIMARY KEY CHECK (id = 1), |
||||
|
activeDid TEXT REFERENCES accounts(did) ON DELETE RESTRICT, |
||||
|
lastUpdated TEXT NOT NULL DEFAULT (datetime('now')) |
||||
|
); |
||||
|
|
||||
|
-- Add performance indexes |
||||
|
CREATE UNIQUE INDEX IF NOT EXISTS idx_active_identity_single_record ON active_identity(id); |
||||
|
CREATE INDEX IF NOT EXISTS idx_accounts_pick ON accounts(dateCreated, did); |
||||
|
|
||||
|
-- Seed singleton row (only if not already exists) |
||||
|
INSERT INTO active_identity (id, activeDid, lastUpdated) |
||||
|
SELECT 1, NULL, datetime('now') |
||||
|
WHERE NOT EXISTS (SELECT 1 FROM active_identity WHERE id = 1); |
||||
|
|
||||
|
-- Add hasBackedUpSeed field to settings |
||||
|
ALTER TABLE settings ADD COLUMN hasBackedUpSeed BOOLEAN DEFAULT FALSE; |
||||
|
|
||||
|
-- Create automatic timestamp trigger |
||||
|
CREATE TRIGGER IF NOT EXISTS trg_active_identity_touch |
||||
|
AFTER UPDATE ON active_identity |
||||
|
FOR EACH ROW |
||||
|
BEGIN |
||||
|
UPDATE active_identity |
||||
|
SET lastUpdated = datetime('now') |
||||
|
WHERE id = 1; |
||||
|
END; |
||||
|
` |
||||
|
} |
||||
|
``` |
||||
|
|
||||
|
|
||||
|
## Migration Service Updates Required |
||||
|
|
||||
|
### Enhanced Validation Logic |
||||
|
**File**: `src/services/migrationService.ts` |
||||
|
|
||||
|
The existing validation for migration 003 needs to be enhanced to check for: |
||||
|
- **Trigger existence**: `trg_active_identity_touch` |
||||
|
- **Performance index**: `idx_accounts_pick` |
||||
|
- **Foreign key constraint**: `ON DELETE RESTRICT` |
||||
|
|
||||
|
### Enhanced Schema Detection |
||||
|
**File**: `src/services/migrationService.ts` |
||||
|
|
||||
|
The existing schema detection for migration 003 needs to be enhanced to verify: |
||||
|
- **Table structure**: Enhanced constraints |
||||
|
- **Trigger presence**: Automatic timestamp updates |
||||
|
- **Index presence**: Performance optimization |
||||
|
|
||||
|
## Risk Assessment |
||||
|
|
||||
|
### Low Risk Changes |
||||
|
- **Performance Index**: Additive only, no data changes |
||||
|
- **Trigger Creation**: Additive only, improves consistency |
||||
|
- **Migration Rewrite**: Clean implementation, no additional migrations |
||||
|
|
||||
|
### Medium Risk Changes |
||||
|
- **Foreign Key Change**: `ON DELETE RESTRICT` is more restrictive |
||||
|
- **Validation Updates**: Need to test enhanced validation logic |
||||
|
|
||||
|
### Mitigation Strategies |
||||
|
1. **Comprehensive Testing**: Test migration on various database states |
||||
|
2. **Development Phase**: Since we're in active development, risk is minimal |
||||
|
3. **Clean Implementation**: Single migration with all enhancements |
||||
|
4. **Validation Coverage**: Enhanced validation ensures correctness |
||||
|
|
||||
|
## Implementation Timeline |
||||
|
|
||||
|
### Phase 1: Migration Rewrite |
||||
|
- [ ] Update migration 003 with enhanced constraints |
||||
|
- [ ] Add enhanced validation logic |
||||
|
- [ ] Add enhanced schema detection logic |
||||
|
- [ ] Test migration on clean database |
||||
|
|
||||
|
### Phase 2: Testing |
||||
|
- [ ] Test migration on existing databases |
||||
|
- [ ] Validate foreign key constraints work correctly |
||||
|
- [ ] Test trigger functionality |
||||
|
- [ ] Test performance improvements |
||||
|
|
||||
|
### Phase 3: Deployment |
||||
|
- [ ] Deploy enhanced migration to development |
||||
|
- [ ] Monitor migration success rates |
||||
|
- [ ] Deploy to production |
||||
|
- [ ] Monitor for any issues |
||||
|
|
||||
|
## Code Changes Required |
||||
|
|
||||
|
### Files to Modify |
||||
|
1. **`src/db-sql/migration.ts`** - Update migration 003 with enhanced constraints |
||||
|
2. **`src/services/migrationService.ts`** - Add enhanced validation and detection logic |
||||
|
3. **`src/utils/PlatformServiceMixin.ts`** - Remove manual timestamp updates |
||||
|
|
||||
|
### Estimated Impact |
||||
|
- **Migration File**: ~20 lines modified (enhanced constraints) |
||||
|
- **Migration Service**: ~50 lines added (enhanced validation) |
||||
|
- **PlatformServiceMixin**: ~20 lines removed (manual timestamps) |
||||
|
- **Total**: ~50 lines changed |
||||
|
|
||||
|
## Conclusion |
||||
|
|
||||
|
The proposed database changes are **feasible and beneficial** with a much simpler implementation: |
||||
|
|
||||
|
**Benefits**: |
||||
|
- Improved data integrity with `ON DELETE RESTRICT` |
||||
|
- Automatic timestamp consistency |
||||
|
- Better query performance |
||||
|
- Cleaner code (no manual timestamp updates) |
||||
|
- **Simpler implementation** - just rewrite migration 003 |
||||
|
|
||||
|
**Risks**: |
||||
|
- More restrictive foreign key constraints |
||||
|
- Enhanced validation logic needs testing |
||||
|
|
||||
|
**Recommendation**: Proceed with **rewriting migration 003** as it provides the cleanest path forward with minimal complexity and maximum benefit. |
||||
|
|
||||
|
|
||||
|
--- |
||||
|
|
||||
|
## Part 2: Active Identity System Upgrade Plan |
||||
|
|
||||
|
# Active Identity System Upgrade Plan |
||||
|
|
||||
|
## Overview |
||||
|
|
||||
|
This document outlines a comprehensive upgrade to the `$getActiveIdentity` system |
||||
|
to address current ambiguities, race conditions, and improve overall robustness. |
||||
|
|
||||
|
## Current Issues Identified |
||||
|
|
||||
|
### 1. **Ambiguous Return States** |
||||
|
|
||||
|
- Current: Returns `{ activeDid: string }` where empty string conflates multiple states |
||||
|
- Problem: Cannot distinguish between "no accounts", "migration gap", "corruption cleared" |
||||
|
- Impact: UI cannot provide appropriate user guidance |
||||
|
|
||||
|
### 2. **Race Conditions (TOCTOU)** |
||||
|
|
||||
|
- Current: Read → Write → Re-read across multiple statements |
||||
|
- Problem: No transactional guard, potential for inconsistent state |
||||
|
- Impact: Rare but possible data corruption scenarios |
||||
|
|
||||
|
### 3. **No Single-Row Enforcement** |
||||
|
|
||||
|
- Current: App logic assumes `id=1` singleton, but DB doesn't enforce |
||||
|
- Problem: Multiple rows could theoretically exist |
||||
|
- Impact: Unpredictable behavior |
||||
|
|
||||
|
### 4. **Deletion Hazards** |
||||
|
|
||||
|
- Current: No protection against deleting active account |
||||
|
- Problem: App "discovers" corruption after the fact |
||||
|
- Impact: Poor user experience, potential data loss |
||||
|
|
||||
|
### 5. **Inconsistent Updates** |
||||
|
|
||||
|
- Current: `lastUpdated` only set on some code paths |
||||
|
- Problem: Audit trail incomplete |
||||
|
- Impact: Debugging difficulties |
||||
|
|
||||
|
## Proposed Solution Architecture |
||||
|
|
||||
|
### Database Schema Changes |
||||
|
|
||||
|
```sql |
||||
|
-- Enhanced active_identity table with constraints |
||||
|
CREATE TABLE IF NOT EXISTS active_identity ( |
||||
|
id INTEGER PRIMARY KEY CHECK (id = 1), |
||||
|
activeDid TEXT REFERENCES accounts(did) ON DELETE RESTRICT, |
||||
|
lastUpdated TEXT NOT NULL DEFAULT (datetime('now')) |
||||
|
); |
||||
|
|
||||
|
-- Automatic timestamp updates |
||||
|
CREATE TRIGGER IF NOT EXISTS trg_active_identity_touch |
||||
|
AFTER UPDATE ON active_identity |
||||
|
FOR EACH ROW |
||||
|
BEGIN |
||||
|
UPDATE active_identity |
||||
|
SET lastUpdated = datetime('now') |
||||
|
WHERE id = 1; |
||||
|
END; |
||||
|
|
||||
|
-- Deterministic account selection index |
||||
|
CREATE INDEX IF NOT EXISTS idx_accounts_pick |
||||
|
ON accounts(dateCreated, did); |
||||
|
|
||||
|
-- Seed singleton row |
||||
|
INSERT INTO active_identity (id, activeDid) |
||||
|
SELECT 1, NULL |
||||
|
WHERE NOT EXISTS (SELECT 1 FROM active_identity WHERE id = 1); |
||||
|
``` |
||||
|
|
||||
|
### Type System Enhancement |
||||
|
|
||||
|
```typescript |
||||
|
type ActiveIdentity = |
||||
|
| { state: 'ok'; activeDid: string } |
||||
|
| { state: 'unset'; activeDid: '' } // row exists, but no active set yet |
||||
|
| { state: 'auto-selected'; activeDid: string } // we selected & saved first account |
||||
|
| { state: 'empty-accounts'; activeDid: '' } // there are no accounts to select |
||||
|
| { state: 'cleared-corrupt'; activeDid: '' } // DB had a non-existent DID; cleared |
||||
|
| { state: 'error'; activeDid: '' }; |
||||
|
``` |
||||
|
|
||||
|
## Migration Strategy |
||||
|
|
||||
|
### Phase 1: Database Schema Migration |
||||
|
|
||||
|
**Files to modify:** |
||||
|
|
||||
|
- `src/db-sql/migration.ts` - Add new migration |
||||
|
- `src/services/migrationService.ts` - Update validation logic |
||||
|
|
||||
|
**Migration Steps:** |
||||
|
|
||||
|
1. Add foreign key constraint to `active_identity.activeDid` |
||||
|
2. Add `ON DELETE RESTRICT` constraint |
||||
|
3. Create timestamp trigger |
||||
|
4. Add deterministic index |
||||
|
5. Ensure singleton row exists |
||||
|
|
||||
|
**Risk Assessment:** LOW |
||||
|
- Additive changes only |
||||
|
- Existing data preserved |
||||
|
- Rollback possible |
||||
|
|
||||
|
### Phase 2: Core Method Refactor |
||||
|
|
||||
|
**Files to modify:** |
||||
|
|
||||
|
- `src/utils/PlatformServiceMixin.ts` - Replace `$getActiveIdentity` |
||||
|
- `src/interfaces/` - Add new type definitions |
||||
|
|
||||
|
**Changes:** |
||||
|
|
||||
|
1. Implement transactional `$getActiveIdentity` with explicit states |
||||
|
2. Add `$setActiveIdentity` method |
||||
|
3. Add `$deleteAccountSafely` method |
||||
|
4. Update return type to `ActiveIdentity` |
||||
|
|
||||
|
**Risk Assessment:** MEDIUM |
||||
|
|
||||
|
- Breaking change to return type |
||||
|
- Requires coordinated updates across codebase |
||||
|
- Extensive testing needed |
||||
|
|
||||
|
### Phase 3: Consumer Updates |
||||
|
|
||||
|
**Files to modify:** |
||||
|
|
||||
|
- All Vue components using `$getActiveIdentity` |
||||
|
- Router guards |
||||
|
- Service layer components |
||||
|
|
||||
|
**Changes:** |
||||
|
|
||||
|
1. Update all callers to handle new return type |
||||
|
2. Implement state-specific UI logic |
||||
|
3. Add appropriate user messaging |
||||
|
|
||||
|
**Risk Assessment:** HIGH |
||||
|
|
||||
|
- Wide impact across codebase |
||||
|
- UI/UX changes required |
||||
|
- Extensive testing needed |
||||
|
|
||||
|
## Implementation Phases |
||||
|
|
||||
|
### Phase 1: Database Foundation |
||||
|
|
||||
|
- [ ] Create migration for schema changes |
||||
|
- [ ] Test migration on development databases |
||||
|
- [ ] Validate foreign key constraints work correctly |
||||
|
- [ ] Test rollback scenarios |
||||
|
|
||||
|
### Phase 2: Core Implementation |
||||
|
|
||||
|
- [ ] Implement new `$getActiveIdentity` method |
||||
|
- [ ] Add `$setActiveIdentity` method |
||||
|
- [ ] Add `$deleteAccountSafely` method |
||||
|
- [ ] Create comprehensive unit tests |
||||
|
- [ ] Test transactional behavior |
||||
|
|
||||
|
### Phase 3: Consumer Updates |
||||
|
|
||||
|
- [ ] Audit all current usage of `$getActiveIdentity` |
||||
|
- [ ] Create migration guide for components |
||||
|
- [ ] Update critical path components first |
||||
|
- [ ] Implement state-specific UI logic |
||||
|
|
||||
|
### Phase 4: Testing & Rollout |
||||
|
|
||||
|
- [ ] End-to-end testing |
||||
|
- [ ] Performance testing |
||||
|
- [ ] User acceptance testing |
||||
|
- [ ] Gradual rollout with feature flags |
||||
|
|
||||
|
## Backward Compatibility Strategy |
||||
|
|
||||
|
### Gradual Migration Approach |
||||
|
|
||||
|
The gradual migration strategy allows us to implement the new active identity system without breaking existing functionality. This approach minimizes risk and provides a clear path for incremental updates. |
||||
|
|
||||
|
#### Phase 1: Dual Method Implementation |
||||
|
|
||||
|
- **Keep existing method**: Leave current `$getActiveIdentity` unchanged (no renaming) |
||||
|
- **Add new method**: Implement `$getActiveIdentityV2` with new return type and logic |
||||
|
- **Feature flag control**: Use `FEATURE_FLAG_ACTIVE_IDENTITY_V2` to control which method is used |
||||
|
- **Default to existing**: Start with existing method enabled to ensure no breaking changes |
||||
|
|
||||
|
#### Phase 2: Component Migration |
||||
|
|
||||
|
- **Audit usage**: Identify all components using `$getActiveIdentity` |
||||
|
- **Create migration guide**: Document the changes needed for each component type |
||||
|
- **Update incrementally**: Migrate components to use `$getActiveIdentityV2` one |
||||
|
by one, starting with non-critical paths |
||||
|
- **Test each migration**: Validate each component works with the new method |
||||
|
before proceeding |
||||
|
|
||||
|
#### Phase 3: Feature Flag Rollout |
||||
|
|
||||
|
- **Enable for migrated components**: Switch feature flag for components that have been updated |
||||
|
- **Monitor performance**: Track any performance or behavior changes |
||||
|
- **Gradual enablement**: Enable the new method for more components as they're migrated |
||||
|
- **Fallback capability**: Keep legacy method available for rollback if issues arise |
||||
|
|
||||
|
#### Phase 4: Legacy Cleanup |
||||
|
|
||||
|
- **Remove feature flag**: Once all components are migrated, remove the feature flag |
||||
|
- **Replace existing method**: Replace the implementation of `$getActiveIdentity` with the V2 logic |
||||
|
- **Remove V2 method**: Delete `$getActiveIdentityV2` and related code |
||||
|
- **Update documentation**: Remove references to the V2 method |
||||
|
- **Final validation**: Ensure no remaining references to V2 method |
||||
|
|
||||
|
#### Benefits of This Approach |
||||
|
|
||||
|
- **Zero downtime**: No breaking changes during migration |
||||
|
- **Incremental testing**: Each component can be tested individually |
||||
|
- **Easy rollback**: Can revert individual components or entire system if needed |
||||
|
- **Clear progress tracking**: Easy to see which components still need migration |
||||
|
- **Reduced risk**: Issues are isolated to individual components rather than system-wide |
||||
|
|
||||
|
## Risk Mitigation |
||||
|
|
||||
|
### Database Risks |
||||
|
|
||||
|
- **Foreign Key Violations**: Test with existing data |
||||
|
- **Migration Failures**: Comprehensive rollback plan |
||||
|
- **Performance Impact**: Monitor query performance |
||||
|
|
||||
|
### Code Risks |
||||
|
|
||||
|
- **Breaking Changes**: Extensive testing, gradual rollout |
||||
|
- **Race Conditions**: Comprehensive unit tests |
||||
|
- **State Management**: Clear documentation, examples |
||||
|
|
||||
|
### User Experience Risks |
||||
|
|
||||
|
- **Confusing States**: Clear UI messaging |
||||
|
- **Data Loss**: Backup strategies, validation |
||||
|
- **Performance**: Monitor response times |
||||
|
|
||||
|
## Success Metrics |
||||
|
|
||||
|
### Technical Metrics |
||||
|
|
||||
|
- Zero race condition incidents |
||||
|
- 100% test coverage for new methods |
||||
|
- <50ms average response time |
||||
|
- Zero data corruption incidents |
||||
|
|
||||
|
### User Experience Metrics |
||||
|
|
||||
|
- Clear state-specific messaging |
||||
|
- Reduced user confusion |
||||
|
- Improved onboarding flow |
||||
|
- Faster account switching |
||||
|
|
||||
|
## Rollback Plan |
||||
|
|
||||
|
### Database Rollback |
||||
|
|
||||
|
1. Remove foreign key constraints |
||||
|
2. Remove triggers |
||||
|
3. Remove indexes |
||||
|
4. Restore previous migration state |
||||
|
|
||||
|
### Code Rollback |
||||
|
|
||||
|
1. Revert to previous `$getActiveIdentity` implementation |
||||
|
2. Remove new type definitions |
||||
|
3. Restore previous component logic |
||||
|
4. Remove new methods |
||||
|
|
||||
|
## Testing Strategy |
||||
|
|
||||
|
### Unit Tests |
||||
|
|
||||
|
- Test all state transitions |
||||
|
- Test transactional behavior |
||||
|
- Test error conditions |
||||
|
- Test edge cases |
||||
|
|
||||
|
### Integration Tests |
||||
|
|
||||
|
- Test with real database |
||||
|
- Test migration scenarios |
||||
|
- Test concurrent access |
||||
|
- Test foreign key constraints |
||||
|
|
||||
|
### End-to-End Tests |
||||
|
|
||||
|
- Test complete user flows |
||||
|
- Test account creation/deletion |
||||
|
- Test active identity switching |
||||
|
- Test error recovery |
||||
|
|
||||
|
## Documentation Requirements |
||||
|
|
||||
|
### Developer Documentation |
||||
|
|
||||
|
- Migration guide for components |
||||
|
- API documentation for new methods |
||||
|
- Type definitions and examples |
||||
|
- Best practices guide |
||||
|
|
||||
|
### User Documentation |
||||
|
|
||||
|
- State-specific UI messaging |
||||
|
- Error message guidelines |
||||
|
- Onboarding flow updates |
||||
|
- Troubleshooting guide |
||||
|
|
||||
|
## Conclusion |
||||
|
|
||||
|
This upgrade addresses critical architectural issues while providing a clear path |
||||
|
forward. The phased approach minimizes risk while ensuring thorough testing and |
||||
|
validation at each step. |
||||
|
|
||||
|
**Recommendation:** Proceed with Phase 1 (Database Schema) immediately, as it |
||||
|
provides immediate benefits with minimal risk. The gradual migration approach allows |
||||
|
for incremental updates without breaking existing functionality. |
Loading…
Reference in new issue