Browse Source

refactor: consolidate active identity migrations 004-006 into single migration

- Consolidate migrations 004, 005, and 006 into single 004_active_identity_management
- Remove redundant migrations 005 (constraint_fix) and 006 (settings_cleanup)
- Implement security-first approach with ON DELETE RESTRICT constraint from start
- Include comprehensive data migration from settings.activeDid to active_identity.activeDid
- Add proper cleanup of orphaned settings records and legacy activeDid values
- Update migrationService.ts validation logic to reflect consolidated structure
- Fix migration name references and enhance validation for hasBackedUpSeed column
- Reduce migration complexity from 3 separate operations to 1 atomic operation
- Maintain data integrity with foreign key constraints and performance indexes

Migration successfully tested on web platform with no data loss or corruption.
Active DID properly migrated: did:ethr:0xCA26A3959D32D2eB5459cE08203DbC4e62e79F5D

Files changed:
- src/db-sql/migration.ts: Consolidated 3 migrations into 1 (-46 lines)
- src/services/migrationService.ts: Updated validation logic (+13 lines)
pull/188/head
Matthew Raymer 7 hours ago
parent
commit
24ec81b0ba
  1. 53
      src/db-sql/migration.ts
  2. 16
      src/services/migrationService.ts

53
src/db-sql/migration.ts

@ -141,9 +141,11 @@ const MIGRATIONS = [
`,
},
{
name: "004_active_identity_and_seed_backup",
name: "004_active_identity_management",
sql: `
-- Migration 004: active_identity_and_seed_backup
-- Migration 004: active_identity_management (CONSOLIDATED)
-- Combines original migrations 004, 005, and 006 into single atomic operation
-- CRITICAL SECURITY: Uses ON DELETE RESTRICT constraint from the start
-- Assumes master code deployed with migration 003 (hasBackedUpSeed)
-- Enable foreign key constraints for data integrity
@ -152,12 +154,12 @@ const MIGRATIONS = [
-- 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 foreign key constraint
-- Create active_identity table with SECURE constraint (ON DELETE RESTRICT)
-- This prevents accidental account deletion - critical security feature
CREATE TABLE IF NOT EXISTS active_identity (
id INTEGER PRIMARY KEY CHECK (id = 1),
activeDid TEXT DEFAULT NULL, -- NULL instead of empty string
lastUpdated TEXT NOT NULL DEFAULT (datetime('now')),
FOREIGN KEY (activeDid) REFERENCES accounts(did) ON DELETE SET NULL
activeDid TEXT REFERENCES accounts(did) ON DELETE RESTRICT,
lastUpdated TEXT NOT NULL DEFAULT (datetime('now'))
);
-- Add performance indexes
@ -175,45 +177,10 @@ const MIGRATIONS = [
lastUpdated = datetime('now')
WHERE id = 1
AND EXISTS (SELECT 1 FROM settings WHERE id = 1 AND activeDid IS NOT NULL AND activeDid != '');
`,
},
{
name: "005_active_identity_constraint_fix",
sql: `
-- Migration 005: Fix foreign key constraint to ON DELETE RESTRICT
-- CRITICAL SECURITY FIX: Prevents accidental account deletion
PRAGMA foreign_keys = ON;
-- Recreate table with ON DELETE RESTRICT constraint (SECURITY FIX)
CREATE TABLE active_identity_new (
id INTEGER PRIMARY KEY CHECK (id = 1),
activeDid TEXT REFERENCES accounts(did) ON DELETE RESTRICT,
lastUpdated TEXT NOT NULL DEFAULT (datetime('now'))
);
-- Copy existing data
INSERT INTO active_identity_new (id, activeDid, lastUpdated)
SELECT id, activeDid, lastUpdated FROM active_identity;
-- Replace old table
DROP TABLE active_identity;
ALTER TABLE active_identity_new RENAME TO active_identity;
-- Recreate indexes
CREATE UNIQUE INDEX IF NOT EXISTS idx_active_identity_single_record ON active_identity(id);
`,
},
{
name: "006_settings_cleanup",
sql: `
-- Migration 006: Settings cleanup
-- Remove orphaned settings records and clear legacy activeDid values
-- Remove orphaned settings records (accountDid is null)
-- CLEANUP: Remove orphaned settings records and clear legacy activeDid values
-- This completes the migration from settings-based to table-based active identity
DELETE FROM settings WHERE accountDid IS NULL;
-- Clear any remaining activeDid values in settings
UPDATE settings SET activeDid = NULL;
`,
},

16
src/services/migrationService.ts

@ -374,7 +374,7 @@ async function validateMigrationApplication<T>(
} else {
validation.hasExpectedColumns = true;
}
} else if (migration.name === "003_active_identity_and_seed_backup") {
} else if (migration.name === "004_active_identity_management") {
// Validate active_identity table exists and has correct structure
const activeIdentityExists = await validateTableExists(
"active_identity",
@ -409,6 +409,8 @@ async function validateMigrationApplication<T>(
}
// Check that hasBackedUpSeed column exists in settings table
// Note: This validation is included here because migration 004 is consolidated
// and includes the functionality from the original migration 003
const hasBackedUpSeedExists = await validateColumnExists(
"settings",
"hasBackedUpSeed",
@ -493,7 +495,7 @@ async function isSchemaAlreadyPresent<T>(
} catch (error) {
return false;
}
} else if (migration.name === "004_active_identity_and_seed_backup") {
} else if (migration.name === "004_active_identity_management") {
// Check if active_identity table exists and has correct structure
try {
// Check that active_identity table exists
@ -515,7 +517,15 @@ async function isSchemaAlreadyPresent<T>(
await sqlQuery(
`SELECT id, activeDid, lastUpdated FROM active_identity LIMIT 1`,
);
return true;
// Also check that hasBackedUpSeed column exists in settings
// This is included because migration 004 is consolidated
try {
await sqlQuery(`SELECT hasBackedUpSeed FROM settings LIMIT 1`);
return true;
} catch (error) {
return false;
}
} catch (error) {
return false;
}

Loading…
Cancel
Save