From aec40a4d03fa3e5134c31468c8002ebdde9febe5 Mon Sep 17 00:00:00 2001 From: Leendert de Borst Date: Fri, 30 Jan 2026 23:34:07 +0100 Subject: [PATCH] Add major version bump to vault version to prevent runtime errors in older unsupported clients (#1535) --- .../src/utils/dist/core/vault/index.d.mts | 2 +- .../src/utils/dist/core/vault/index.d.ts | 2 +- .../src/utils/dist/core/vault/index.js | 22 +- .../src/utils/dist/core/vault/index.mjs | 22 +- .../app/vaultstore/models/VaultSql.kt | 13 + .../app/vaultstore/models/VaultVersions.kt | 9 +- .../mobile-app/ios/VaultModels/VaultSql.swift | 13 + .../ios/VaultModels/VaultVersions.swift | 9 +- .../utils/dist/core/vault/index.d.mts | 2 +- .../utils/dist/core/vault/index.d.ts | 2 +- .../mobile-app/utils/dist/core/vault/index.js | 22 +- .../utils/dist/core/vault/index.mjs | 22 +- .../wwwroot/js/dist/core/vault/index.d.mts | 2 +- .../wwwroot/js/dist/core/vault/index.d.ts | 2 +- .../wwwroot/js/dist/core/vault/index.js | 22 +- .../wwwroot/js/dist/core/vault/index.mjs | 22 +- ...0221620_2.0.0-MajorVersionBump.Designer.cs | 675 ++++++++++++++++++ .../20260130221620_2.0.0-MajorVersionBump.cs | 23 + .../Scripts/MigrationSql/000_FullSchema.sql | 6 + ..._20260130221620_2.0.0-MajorVersionBump.sql | 6 + core/vault/src/sql/SqlConstants.ts | 11 + core/vault/src/sql/VaultVersions.ts | 9 +- 22 files changed, 897 insertions(+), 21 deletions(-) create mode 100644 apps/server/Databases/AliasClientDb/Migrations/20260130221620_2.0.0-MajorVersionBump.Designer.cs create mode 100644 apps/server/Databases/AliasClientDb/Migrations/20260130221620_2.0.0-MajorVersionBump.cs create mode 100644 apps/server/Databases/AliasClientDb/Scripts/MigrationSql/012_20251213111207_1.7.0-FieldBasedDataModelUpdate_to_20260130221620_2.0.0-MajorVersionBump.sql diff --git a/apps/browser-extension/src/utils/dist/core/vault/index.d.mts b/apps/browser-extension/src/utils/dist/core/vault/index.d.mts index 033a999f0..0ee327dbe 100644 --- a/apps/browser-extension/src/utils/dist/core/vault/index.d.mts +++ b/apps/browser-extension/src/utils/dist/core/vault/index.d.mts @@ -122,7 +122,7 @@ declare const VAULT_VERSIONS: VaultVersion[]; * Complete database schema SQL (latest version) * Auto-generated from EF Core migrations */ -declare const COMPLETE_SCHEMA_SQL = "\n\uFEFFCREATE TABLE IF NOT EXISTS \"__EFMigrationsHistory\" (\n \"MigrationId\" TEXT NOT NULL CONSTRAINT \"PK___EFMigrationsHistory\" PRIMARY KEY,\n \"ProductVersion\" TEXT NOT NULL\n);\n\nBEGIN TRANSACTION;\nCREATE TABLE \"Aliases\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_Aliases\" PRIMARY KEY,\n \"Gender\" VARCHAR NULL,\n \"FirstName\" VARCHAR NULL,\n \"LastName\" VARCHAR NULL,\n \"NickName\" VARCHAR NULL,\n \"BirthDate\" TEXT NOT NULL,\n \"AddressStreet\" VARCHAR NULL,\n \"AddressCity\" VARCHAR NULL,\n \"AddressState\" VARCHAR NULL,\n \"AddressZipCode\" VARCHAR NULL,\n \"AddressCountry\" VARCHAR NULL,\n \"Hobbies\" TEXT NULL,\n \"EmailPrefix\" TEXT NULL,\n \"PhoneMobile\" TEXT NULL,\n \"BankAccountIBAN\" TEXT NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"UpdatedAt\" TEXT NOT NULL\n);\n\nCREATE TABLE \"Services\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_Services\" PRIMARY KEY,\n \"Name\" TEXT NULL,\n \"Url\" TEXT NULL,\n \"Logo\" BLOB NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"UpdatedAt\" TEXT NOT NULL\n);\n\nCREATE TABLE \"Credentials\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_Credentials\" PRIMARY KEY,\n \"AliasId\" TEXT NOT NULL,\n \"Notes\" TEXT NULL,\n \"Username\" TEXT NOT NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"UpdatedAt\" TEXT NOT NULL,\n \"ServiceId\" TEXT NOT NULL,\n CONSTRAINT \"FK_Credentials_Aliases_AliasId\" FOREIGN KEY (\"AliasId\") REFERENCES \"Aliases\" (\"Id\") ON DELETE CASCADE,\n CONSTRAINT \"FK_Credentials_Services_ServiceId\" FOREIGN KEY (\"ServiceId\") REFERENCES \"Services\" (\"Id\") ON DELETE CASCADE\n);\n\nCREATE TABLE \"Attachment\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_Attachment\" PRIMARY KEY,\n \"Filename\" TEXT NOT NULL,\n \"Blob\" BLOB NOT NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"UpdatedAt\" TEXT NOT NULL,\n \"CredentialId\" TEXT NOT NULL,\n CONSTRAINT \"FK_Attachment_Credentials_CredentialId\" FOREIGN KEY (\"CredentialId\") REFERENCES \"Credentials\" (\"Id\") ON DELETE CASCADE\n);\n\nCREATE TABLE \"Passwords\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_Passwords\" PRIMARY KEY,\n \"Value\" TEXT NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"UpdatedAt\" TEXT NOT NULL,\n \"CredentialId\" TEXT NOT NULL,\n CONSTRAINT \"FK_Passwords_Credentials_CredentialId\" FOREIGN KEY (\"CredentialId\") REFERENCES \"Credentials\" (\"Id\") ON DELETE CASCADE\n);\n\nCREATE INDEX \"IX_Attachment_CredentialId\" ON \"Attachment\" (\"CredentialId\");\n\nCREATE INDEX \"IX_Credentials_AliasId\" ON \"Credentials\" (\"AliasId\");\n\nCREATE INDEX \"IX_Credentials_ServiceId\" ON \"Credentials\" (\"ServiceId\");\n\nCREATE INDEX \"IX_Passwords_CredentialId\" ON \"Passwords\" (\"CredentialId\");\n\nINSERT INTO \"__EFMigrationsHistory\" (\"MigrationId\", \"ProductVersion\")\nVALUES ('20240708094944_1.0.0-InitialMigration', '9.0.4');\n\nINSERT INTO \"__EFMigrationsHistory\" (\"MigrationId\", \"ProductVersion\")\nVALUES ('20240708224522_1.0.1-EmptyTestMigration', '9.0.4');\n\nALTER TABLE \"Aliases\" RENAME COLUMN \"EmailPrefix\" TO \"Email\";\n\nINSERT INTO \"__EFMigrationsHistory\" (\"MigrationId\", \"ProductVersion\")\nVALUES ('20240711204207_1.0.2-ChangeEmailColumn', '9.0.4');\n\nCREATE TABLE \"EncryptionKeys\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_EncryptionKeys\" PRIMARY KEY,\n \"PublicKey\" TEXT NOT NULL,\n \"PrivateKey\" TEXT NOT NULL,\n \"IsPrimary\" INTEGER NOT NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"UpdatedAt\" TEXT NOT NULL\n);\n\nINSERT INTO \"__EFMigrationsHistory\" (\"MigrationId\", \"ProductVersion\")\nVALUES ('20240729105618_1.1.0-AddPkiTables', '9.0.4');\n\nCREATE TABLE \"Settings\" (\n \"Key\" TEXT NOT NULL CONSTRAINT \"PK_Settings\" PRIMARY KEY,\n \"Value\" TEXT NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"UpdatedAt\" TEXT NOT NULL\n);\n\nINSERT INTO \"__EFMigrationsHistory\" (\"MigrationId\", \"ProductVersion\")\nVALUES ('20240805073413_1.2.0-AddSettingsTable', '9.0.4');\n\nCREATE TABLE \"ef_temp_Aliases\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_Aliases\" PRIMARY KEY,\n \"BirthDate\" TEXT NOT NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"Email\" TEXT NULL,\n \"FirstName\" VARCHAR NULL,\n \"Gender\" VARCHAR NULL,\n \"LastName\" VARCHAR NULL,\n \"NickName\" VARCHAR NULL,\n \"UpdatedAt\" TEXT NOT NULL\n);\n\nINSERT INTO \"ef_temp_Aliases\" (\"Id\", \"BirthDate\", \"CreatedAt\", \"Email\", \"FirstName\", \"Gender\", \"LastName\", \"NickName\", \"UpdatedAt\")\nSELECT \"Id\", \"BirthDate\", \"CreatedAt\", \"Email\", \"FirstName\", \"Gender\", \"LastName\", \"NickName\", \"UpdatedAt\"\nFROM \"Aliases\";\n\nCOMMIT;\n\nPRAGMA foreign_keys = 0;\n\nBEGIN TRANSACTION;\nDROP TABLE \"Aliases\";\n\nALTER TABLE \"ef_temp_Aliases\" RENAME TO \"Aliases\";\n\nCOMMIT;\n\nPRAGMA foreign_keys = 1;\n\nINSERT INTO \"__EFMigrationsHistory\" (\"MigrationId\", \"ProductVersion\")\nVALUES ('20240805122422_1.3.0-UpdateIdentityStructure', '9.0.4');\n\nBEGIN TRANSACTION;\nCREATE TABLE \"ef_temp_Credentials\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_Credentials\" PRIMARY KEY,\n \"AliasId\" TEXT NOT NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"Notes\" TEXT NULL,\n \"ServiceId\" TEXT NOT NULL,\n \"UpdatedAt\" TEXT NOT NULL,\n \"Username\" TEXT NULL,\n CONSTRAINT \"FK_Credentials_Aliases_AliasId\" FOREIGN KEY (\"AliasId\") REFERENCES \"Aliases\" (\"Id\") ON DELETE CASCADE,\n CONSTRAINT \"FK_Credentials_Services_ServiceId\" FOREIGN KEY (\"ServiceId\") REFERENCES \"Services\" (\"Id\") ON DELETE CASCADE\n);\n\nINSERT INTO \"ef_temp_Credentials\" (\"Id\", \"AliasId\", \"CreatedAt\", \"Notes\", \"ServiceId\", \"UpdatedAt\", \"Username\")\nSELECT \"Id\", \"AliasId\", \"CreatedAt\", \"Notes\", \"ServiceId\", \"UpdatedAt\", \"Username\"\nFROM \"Credentials\";\n\nCOMMIT;\n\nPRAGMA foreign_keys = 0;\n\nBEGIN TRANSACTION;\nDROP TABLE \"Credentials\";\n\nALTER TABLE \"ef_temp_Credentials\" RENAME TO \"Credentials\";\n\nCOMMIT;\n\nPRAGMA foreign_keys = 1;\n\nBEGIN TRANSACTION;\nCREATE INDEX \"IX_Credentials_AliasId\" ON \"Credentials\" (\"AliasId\");\n\nCREATE INDEX \"IX_Credentials_ServiceId\" ON \"Credentials\" (\"ServiceId\");\n\nCOMMIT;\n\nINSERT INTO \"__EFMigrationsHistory\" (\"MigrationId\", \"ProductVersion\")\nVALUES ('20240812141727_1.3.1-MakeUsernameOptional', '9.0.4');\n\nBEGIN TRANSACTION;\nALTER TABLE \"Settings\" ADD \"IsDeleted\" INTEGER NOT NULL DEFAULT 0;\n\nALTER TABLE \"Services\" ADD \"IsDeleted\" INTEGER NOT NULL DEFAULT 0;\n\nALTER TABLE \"Passwords\" ADD \"IsDeleted\" INTEGER NOT NULL DEFAULT 0;\n\nALTER TABLE \"EncryptionKeys\" ADD \"IsDeleted\" INTEGER NOT NULL DEFAULT 0;\n\nALTER TABLE \"Credentials\" ADD \"IsDeleted\" INTEGER NOT NULL DEFAULT 0;\n\nALTER TABLE \"Attachment\" ADD \"IsDeleted\" INTEGER NOT NULL DEFAULT 0;\n\nALTER TABLE \"Aliases\" ADD \"IsDeleted\" INTEGER NOT NULL DEFAULT 0;\n\nINSERT INTO \"__EFMigrationsHistory\" (\"MigrationId\", \"ProductVersion\")\nVALUES ('20240916105320_1.4.0-AddSyncSupport', '9.0.4');\n\nALTER TABLE \"Attachment\" RENAME TO \"Attachments\";\n\nCREATE TABLE \"ef_temp_Attachments\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_Attachments\" PRIMARY KEY,\n \"Blob\" BLOB NOT NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"CredentialId\" TEXT NOT NULL,\n \"Filename\" TEXT NOT NULL,\n \"IsDeleted\" INTEGER NOT NULL,\n \"UpdatedAt\" TEXT NOT NULL,\n CONSTRAINT \"FK_Attachments_Credentials_CredentialId\" FOREIGN KEY (\"CredentialId\") REFERENCES \"Credentials\" (\"Id\") ON DELETE CASCADE\n);\n\nINSERT INTO \"ef_temp_Attachments\" (\"Id\", \"Blob\", \"CreatedAt\", \"CredentialId\", \"Filename\", \"IsDeleted\", \"UpdatedAt\")\nSELECT \"Id\", \"Blob\", \"CreatedAt\", \"CredentialId\", \"Filename\", \"IsDeleted\", \"UpdatedAt\"\nFROM \"Attachments\";\n\nCOMMIT;\n\nPRAGMA foreign_keys = 0;\n\nBEGIN TRANSACTION;\nDROP TABLE \"Attachments\";\n\nALTER TABLE \"ef_temp_Attachments\" RENAME TO \"Attachments\";\n\nCOMMIT;\n\nPRAGMA foreign_keys = 1;\n\nBEGIN TRANSACTION;\nCREATE INDEX \"IX_Attachments_CredentialId\" ON \"Attachments\" (\"CredentialId\");\n\nCOMMIT;\n\nINSERT INTO \"__EFMigrationsHistory\" (\"MigrationId\", \"ProductVersion\")\nVALUES ('20240917191243_1.4.1-RenameAttachmentsPlural', '9.0.4');\n\nBEGIN TRANSACTION;\nCREATE TABLE \"TotpCodes\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_TotpCodes\" PRIMARY KEY,\n \"Name\" TEXT NOT NULL,\n \"SecretKey\" TEXT NOT NULL,\n \"CredentialId\" TEXT NOT NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"UpdatedAt\" TEXT NOT NULL,\n \"IsDeleted\" INTEGER NOT NULL,\n CONSTRAINT \"FK_TotpCodes_Credentials_CredentialId\" FOREIGN KEY (\"CredentialId\") REFERENCES \"Credentials\" (\"Id\") ON DELETE CASCADE\n);\n\nCREATE INDEX \"IX_TotpCodes_CredentialId\" ON \"TotpCodes\" (\"CredentialId\");\n\nINSERT INTO \"__EFMigrationsHistory\" (\"MigrationId\", \"ProductVersion\")\nVALUES ('20250310131554_1.5.0-AddTotpCodes', '9.0.4');\n\n\nPRAGMA foreign_keys = OFF;\n\n-- Clean up any existing temp tables first\nDROP TABLE IF EXISTS \"__EFMigrationsHistory_temp\";\nDROP TABLE IF EXISTS \"Aliases_temp\";\nDROP TABLE IF EXISTS \"Services_temp\";\nDROP TABLE IF EXISTS \"EncryptionKeys_temp\";\nDROP TABLE IF EXISTS \"Settings_temp\";\nDROP TABLE IF EXISTS \"Credentials_temp\";\nDROP TABLE IF EXISTS \"Attachments_temp\";\nDROP TABLE IF EXISTS \"Passwords_temp\";\nDROP TABLE IF EXISTS \"TotpCodes_temp\";\n\n-- Create backup tables for all data\nCREATE TABLE \"__EFMigrationsHistory_temp\" AS SELECT * FROM \"__EFMigrationsHistory\";\nCREATE TABLE \"Aliases_temp\" AS SELECT * FROM \"Aliases\";\nCREATE TABLE \"Services_temp\" AS SELECT * FROM \"Services\";\nCREATE TABLE \"EncryptionKeys_temp\" AS SELECT * FROM \"EncryptionKeys\";\nCREATE TABLE \"Settings_temp\" AS SELECT * FROM \"Settings\";\nCREATE TABLE \"Credentials_temp\" AS SELECT * FROM \"Credentials\";\nCREATE TABLE \"Attachments_temp\" AS SELECT * FROM \"Attachments\";\nCREATE TABLE \"Passwords_temp\" AS SELECT * FROM \"Passwords\";\nCREATE TABLE \"TotpCodes_temp\" AS SELECT * FROM \"TotpCodes\";\n\n-- Delete orphaned records that do not have a valid FK to the credential object\nDELETE FROM \"Attachments_temp\" WHERE \"CredentialId\" NOT IN (SELECT \"Id\" FROM \"Credentials_temp\");\nDELETE FROM \"Passwords_temp\" WHERE \"CredentialId\" NOT IN (SELECT \"Id\" FROM \"Credentials_temp\");\nDELETE FROM \"TotpCodes_temp\" WHERE \"CredentialId\" NOT IN (SELECT \"Id\" FROM \"Credentials_temp\");\n\n-- Delete orphaned credentials that do not have valid FKs to alias or service objects\nDELETE FROM \"Credentials_temp\" WHERE \"AliasId\" NOT IN (SELECT \"Id\" FROM \"Aliases_temp\");\nDELETE FROM \"Credentials_temp\" WHERE \"ServiceId\" NOT IN (SELECT \"Id\" FROM \"Services_temp\");\n\n-- After cleaning credentials, clean dependent tables again in case we removed credentials\nDELETE FROM \"Attachments_temp\" WHERE \"CredentialId\" NOT IN (SELECT \"Id\" FROM \"Credentials_temp\");\nDELETE FROM \"Passwords_temp\" WHERE \"CredentialId\" NOT IN (SELECT \"Id\" FROM \"Credentials_temp\");\nDELETE FROM \"TotpCodes_temp\" WHERE \"CredentialId\" NOT IN (SELECT \"Id\" FROM \"Credentials_temp\");\n\n-- Drop all existing tables\nDROP TABLE \"TotpCodes\";\nDROP TABLE \"Passwords\";\nDROP TABLE \"Attachments\";\nDROP TABLE \"Credentials\";\nDROP TABLE \"Settings\";\nDROP TABLE \"EncryptionKeys\";\nDROP TABLE \"Services\";\nDROP TABLE \"Aliases\";\nDROP TABLE \"__EFMigrationsHistory\";\n\n-- Recreate tables with proper constraints (no dependencies first)\nCREATE TABLE \"__EFMigrationsHistory\" (\n \"MigrationId\" TEXT NOT NULL CONSTRAINT \"PK___EFMigrationsHistory\" PRIMARY KEY,\n \"ProductVersion\" TEXT NOT NULL\n);\n\nCREATE TABLE \"Aliases\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_Aliases\" PRIMARY KEY,\n \"BirthDate\" TEXT NOT NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"Email\" TEXT NULL,\n \"FirstName\" VARCHAR NULL,\n \"Gender\" VARCHAR NULL,\n \"LastName\" VARCHAR NULL,\n \"NickName\" VARCHAR NULL,\n \"UpdatedAt\" TEXT NOT NULL,\n \"IsDeleted\" INTEGER NOT NULL DEFAULT 0\n);\n\nCREATE TABLE \"Services\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_Services\" PRIMARY KEY,\n \"Name\" TEXT NULL,\n \"Url\" TEXT NULL,\n \"Logo\" BLOB NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"UpdatedAt\" TEXT NOT NULL,\n \"IsDeleted\" INTEGER NOT NULL DEFAULT 0\n);\n\nCREATE TABLE \"EncryptionKeys\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_EncryptionKeys\" PRIMARY KEY,\n \"PublicKey\" TEXT NOT NULL,\n \"PrivateKey\" TEXT NOT NULL,\n \"IsPrimary\" INTEGER NOT NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"UpdatedAt\" TEXT NOT NULL,\n \"IsDeleted\" INTEGER NOT NULL DEFAULT 0\n);\n\nCREATE TABLE \"Settings\" (\n \"Key\" TEXT NOT NULL CONSTRAINT \"PK_Settings\" PRIMARY KEY,\n \"Value\" TEXT NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"UpdatedAt\" TEXT NOT NULL,\n \"IsDeleted\" INTEGER NOT NULL DEFAULT 0\n);\n\n-- Tables with foreign keys\nCREATE TABLE \"Credentials\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_Credentials\" PRIMARY KEY,\n \"AliasId\" TEXT NOT NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"Notes\" TEXT NULL,\n \"ServiceId\" TEXT NOT NULL,\n \"UpdatedAt\" TEXT NOT NULL,\n \"Username\" TEXT NULL,\n \"IsDeleted\" INTEGER NOT NULL DEFAULT 0,\n CONSTRAINT \"FK_Credentials_Aliases_AliasId\" FOREIGN KEY (\"AliasId\") REFERENCES \"Aliases\" (\"Id\") ON DELETE CASCADE,\n CONSTRAINT \"FK_Credentials_Services_ServiceId\" FOREIGN KEY (\"ServiceId\") REFERENCES \"Services\" (\"Id\") ON DELETE CASCADE\n);\n\nCREATE TABLE \"Attachments\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_Attachments\" PRIMARY KEY,\n \"Blob\" BLOB NOT NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"CredentialId\" TEXT NOT NULL,\n \"Filename\" TEXT NOT NULL,\n \"IsDeleted\" INTEGER NOT NULL DEFAULT 0,\n \"UpdatedAt\" TEXT NOT NULL,\n CONSTRAINT \"FK_Attachments_Credentials_CredentialId\" FOREIGN KEY (\"CredentialId\") REFERENCES \"Credentials\" (\"Id\") ON DELETE CASCADE\n);\n\nCREATE TABLE \"Passwords\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_Passwords\" PRIMARY KEY,\n \"Value\" TEXT NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"UpdatedAt\" TEXT NOT NULL,\n \"CredentialId\" TEXT NOT NULL,\n \"IsDeleted\" INTEGER NOT NULL DEFAULT 0,\n CONSTRAINT \"FK_Passwords_Credentials_CredentialId\" FOREIGN KEY (\"CredentialId\") REFERENCES \"Credentials\" (\"Id\") ON DELETE CASCADE\n);\n\nCREATE TABLE \"TotpCodes\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_TotpCodes\" PRIMARY KEY,\n \"Name\" TEXT NOT NULL,\n \"SecretKey\" TEXT NOT NULL,\n \"CredentialId\" TEXT NOT NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"UpdatedAt\" TEXT NOT NULL,\n \"IsDeleted\" INTEGER NOT NULL DEFAULT 0,\n CONSTRAINT \"FK_TotpCodes_Credentials_CredentialId\" FOREIGN KEY (\"CredentialId\") REFERENCES \"Credentials\" (\"Id\") ON DELETE CASCADE\n);\n\n\n-- Restore data from temp tables\nINSERT INTO \"__EFMigrationsHistory\" SELECT * FROM \"__EFMigrationsHistory_temp\";\nINSERT INTO \"Aliases\" SELECT * FROM \"Aliases_temp\";\nINSERT INTO \"Services\" SELECT * FROM \"Services_temp\";\nINSERT INTO \"EncryptionKeys\" SELECT * FROM \"EncryptionKeys_temp\";\nINSERT INTO \"Settings\" SELECT * FROM \"Settings_temp\";\nINSERT INTO \"Credentials\" SELECT * FROM \"Credentials_temp\";\nINSERT INTO \"Attachments\" SELECT * FROM \"Attachments_temp\";\nINSERT INTO \"Passwords\" SELECT * FROM \"Passwords_temp\";\nINSERT INTO \"TotpCodes\" SELECT * FROM \"TotpCodes_temp\";\n\n-- =====================================================================================\n-- Date Format Normalization Migration\n-- =====================================================================================\n-- This migration normalizes ALL date fields to the standard format: 'yyyy-MM-dd HH:mm:ss.fff'\n-- Previously the different clients used different date formats which complicate date parsing.\n-- From version 0.24.0 onwards, all new dates are stored in this standard format.\n\n-- Update Aliases table (CreatedAt, UpdatedAt, BirthDate)\nUPDATE \"Aliases\" SET \"CreatedAt\" =\n CASE\n -- Already in correct format (yyyy-MM-dd HH:mm:ss.fff) - no change\n WHEN \"CreatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9] [0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9][0-9][0-9]'\n THEN \"CreatedAt\"\n\n -- ISO 8601 with milliseconds (yyyy-MM-ddTHH:mm:ss.fffZ) -> Replace T with space, remove Z and everything after .fff\n WHEN \"CreatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]T[0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9]*'\n THEN substr(\"CreatedAt\", 1, 10) || ' ' || substr(\"CreatedAt\", 12, 12)\n\n -- Without milliseconds (yyyy-MM-dd HH:mm:ss or yyyy-MM-ddTHH:mm:ssZ) -> Add .000\n WHEN \"CreatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9][T ][0-9][0-9]:[0-9][0-9]:[0-9][0-9]*'\n THEN substr(\"CreatedAt\", 1, 10) || ' ' || substr(replace(\"CreatedAt\", 'T', ' '), 12, 8) || '.000'\n\n -- Fallback: if none match, keep as-is (edge case)\n ELSE \"CreatedAt\"\n END;\n\nUPDATE \"Aliases\" SET \"UpdatedAt\" =\n CASE\n WHEN \"UpdatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9] [0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9][0-9][0-9]'\n THEN \"UpdatedAt\"\n WHEN \"UpdatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]T[0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9]*'\n THEN substr(\"UpdatedAt\", 1, 10) || ' ' || substr(\"UpdatedAt\", 12, 12)\n WHEN \"UpdatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9][T ][0-9][0-9]:[0-9][0-9]:[0-9][0-9]*'\n THEN substr(\"UpdatedAt\", 1, 10) || ' ' || substr(replace(\"UpdatedAt\", 'T', ' '), 12, 8) || '.000'\n ELSE \"UpdatedAt\"\n END;\n\n-- BirthDate: Always set time to 00:00:00 (no milliseconds for birth dates)\nUPDATE \"Aliases\" SET \"BirthDate\" =\n CASE\n -- If empty or already '0001-01-01 00:00:00', keep as-is\n WHEN \"BirthDate\" = '' OR \"BirthDate\" = '0001-01-01 00:00:00'\n THEN \"BirthDate\"\n\n -- If already in correct format (yyyy-MM-dd 00:00:00), keep as-is\n WHEN \"BirthDate\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9] 00:00:00'\n THEN \"BirthDate\"\n\n -- Extract date part and set time to 00:00:00\n WHEN \"BirthDate\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]*'\n THEN substr(\"BirthDate\", 1, 10) || ' 00:00:00'\n\n -- Fallback\n ELSE \"BirthDate\"\n END;\n\n-- Update Services table (CreatedAt, UpdatedAt)\nUPDATE \"Services\" SET \"CreatedAt\" =\n CASE\n WHEN \"CreatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9] [0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9][0-9][0-9]'\n THEN \"CreatedAt\"\n WHEN \"CreatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]T[0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9]*'\n THEN substr(\"CreatedAt\", 1, 10) || ' ' || substr(\"CreatedAt\", 12, 12)\n WHEN \"CreatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9][T ][0-9][0-9]:[0-9][0-9]:[0-9][0-9]*'\n THEN substr(\"CreatedAt\", 1, 10) || ' ' || substr(replace(\"CreatedAt\", 'T', ' '), 12, 8) || '.000'\n ELSE \"CreatedAt\"\n END;\n\nUPDATE \"Services\" SET \"UpdatedAt\" =\n CASE\n WHEN \"UpdatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9] [0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9][0-9][0-9]'\n THEN \"UpdatedAt\"\n WHEN \"UpdatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]T[0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9]*'\n THEN substr(\"UpdatedAt\", 1, 10) || ' ' || substr(\"UpdatedAt\", 12, 12)\n WHEN \"UpdatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9][T ][0-9][0-9]:[0-9][0-9]:[0-9][0-9]*'\n THEN substr(\"UpdatedAt\", 1, 10) || ' ' || substr(replace(\"UpdatedAt\", 'T', ' '), 12, 8) || '.000'\n ELSE \"UpdatedAt\"\n END;\n\n-- Update EncryptionKeys table (CreatedAt, UpdatedAt)\nUPDATE \"EncryptionKeys\" SET \"CreatedAt\" =\n CASE\n WHEN \"CreatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9] [0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9][0-9][0-9]'\n THEN \"CreatedAt\"\n WHEN \"CreatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]T[0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9]*'\n THEN substr(\"CreatedAt\", 1, 10) || ' ' || substr(\"CreatedAt\", 12, 12)\n WHEN \"CreatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9][T ][0-9][0-9]:[0-9][0-9]:[0-9][0-9]*'\n THEN substr(\"CreatedAt\", 1, 10) || ' ' || substr(replace(\"CreatedAt\", 'T', ' '), 12, 8) || '.000'\n ELSE \"CreatedAt\"\n END;\n\nUPDATE \"EncryptionKeys\" SET \"UpdatedAt\" =\n CASE\n WHEN \"UpdatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9] [0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9][0-9][0-9]'\n THEN \"UpdatedAt\"\n WHEN \"UpdatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]T[0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9]*'\n THEN substr(\"UpdatedAt\", 1, 10) || ' ' || substr(\"UpdatedAt\", 12, 12)\n WHEN \"UpdatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9][T ][0-9][0-9]:[0-9][0-9]:[0-9][0-9]*'\n THEN substr(\"UpdatedAt\", 1, 10) || ' ' || substr(replace(\"UpdatedAt\", 'T', ' '), 12, 8) || '.000'\n ELSE \"UpdatedAt\"\n END;\n\n-- Update Settings table (CreatedAt, UpdatedAt)\nUPDATE \"Settings\" SET \"CreatedAt\" =\n CASE\n WHEN \"CreatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9] [0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9][0-9][0-9]'\n THEN \"CreatedAt\"\n WHEN \"CreatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]T[0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9]*'\n THEN substr(\"CreatedAt\", 1, 10) || ' ' || substr(\"CreatedAt\", 12, 12)\n WHEN \"CreatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9][T ][0-9][0-9]:[0-9][0-9]:[0-9][0-9]*'\n THEN substr(\"CreatedAt\", 1, 10) || ' ' || substr(replace(\"CreatedAt\", 'T', ' '), 12, 8) || '.000'\n ELSE \"CreatedAt\"\n END;\n\nUPDATE \"Settings\" SET \"UpdatedAt\" =\n CASE\n WHEN \"UpdatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9] [0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9][0-9][0-9]'\n THEN \"UpdatedAt\"\n WHEN \"UpdatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]T[0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9]*'\n THEN substr(\"UpdatedAt\", 1, 10) || ' ' || substr(\"UpdatedAt\", 12, 12)\n WHEN \"UpdatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9][T ][0-9][0-9]:[0-9][0-9]:[0-9][0-9]*'\n THEN substr(\"UpdatedAt\", 1, 10) || ' ' || substr(replace(\"UpdatedAt\", 'T', ' '), 12, 8) || '.000'\n ELSE \"UpdatedAt\"\n END;\n\n-- Update Credentials table (CreatedAt, UpdatedAt)\nUPDATE \"Credentials\" SET \"CreatedAt\" =\n CASE\n WHEN \"CreatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9] [0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9][0-9][0-9]'\n THEN \"CreatedAt\"\n WHEN \"CreatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]T[0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9]*'\n THEN substr(\"CreatedAt\", 1, 10) || ' ' || substr(\"CreatedAt\", 12, 12)\n WHEN \"CreatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9][T ][0-9][0-9]:[0-9][0-9]:[0-9][0-9]*'\n THEN substr(\"CreatedAt\", 1, 10) || ' ' || substr(replace(\"CreatedAt\", 'T', ' '), 12, 8) || '.000'\n ELSE \"CreatedAt\"\n END;\n\nUPDATE \"Credentials\" SET \"UpdatedAt\" =\n CASE\n WHEN \"UpdatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9] [0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9][0-9][0-9]'\n THEN \"UpdatedAt\"\n WHEN \"UpdatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]T[0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9]*'\n THEN substr(\"UpdatedAt\", 1, 10) || ' ' || substr(\"UpdatedAt\", 12, 12)\n WHEN \"UpdatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9][T ][0-9][0-9]:[0-9][0-9]:[0-9][0-9]*'\n THEN substr(\"UpdatedAt\", 1, 10) || ' ' || substr(replace(\"UpdatedAt\", 'T', ' '), 12, 8) || '.000'\n ELSE \"UpdatedAt\"\n END;\n\n-- Update Attachments table (CreatedAt, UpdatedAt)\nUPDATE \"Attachments\" SET \"CreatedAt\" =\n CASE\n WHEN \"CreatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9] [0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9][0-9][0-9]'\n THEN \"CreatedAt\"\n WHEN \"CreatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]T[0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9]*'\n THEN substr(\"CreatedAt\", 1, 10) || ' ' || substr(\"CreatedAt\", 12, 12)\n WHEN \"CreatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9][T ][0-9][0-9]:[0-9][0-9]:[0-9][0-9]*'\n THEN substr(\"CreatedAt\", 1, 10) || ' ' || substr(replace(\"CreatedAt\", 'T', ' '), 12, 8) || '.000'\n ELSE \"CreatedAt\"\n END;\n\nUPDATE \"Attachments\" SET \"UpdatedAt\" =\n CASE\n WHEN \"UpdatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9] [0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9][0-9][0-9]'\n THEN \"UpdatedAt\"\n WHEN \"UpdatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]T[0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9]*'\n THEN substr(\"UpdatedAt\", 1, 10) || ' ' || substr(\"UpdatedAt\", 12, 12)\n WHEN \"UpdatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9][T ][0-9][0-9]:[0-9][0-9]:[0-9][0-9]*'\n THEN substr(\"UpdatedAt\", 1, 10) || ' ' || substr(replace(\"UpdatedAt\", 'T', ' '), 12, 8) || '.000'\n ELSE \"UpdatedAt\"\n END;\n\n-- Update Passwords table (CreatedAt, UpdatedAt)\nUPDATE \"Passwords\" SET \"CreatedAt\" =\n CASE\n WHEN \"CreatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9] [0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9][0-9][0-9]'\n THEN \"CreatedAt\"\n WHEN \"CreatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]T[0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9]*'\n THEN substr(\"CreatedAt\", 1, 10) || ' ' || substr(\"CreatedAt\", 12, 12)\n WHEN \"CreatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9][T ][0-9][0-9]:[0-9][0-9]:[0-9][0-9]*'\n THEN substr(\"CreatedAt\", 1, 10) || ' ' || substr(replace(\"CreatedAt\", 'T', ' '), 12, 8) || '.000'\n ELSE \"CreatedAt\"\n END;\n\nUPDATE \"Passwords\" SET \"UpdatedAt\" =\n CASE\n WHEN \"UpdatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9] [0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9][0-9][0-9]'\n THEN \"UpdatedAt\"\n WHEN \"UpdatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]T[0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9]*'\n THEN substr(\"UpdatedAt\", 1, 10) || ' ' || substr(\"UpdatedAt\", 12, 12)\n WHEN \"UpdatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9][T ][0-9][0-9]:[0-9][0-9]:[0-9][0-9]*'\n THEN substr(\"UpdatedAt\", 1, 10) || ' ' || substr(replace(\"UpdatedAt\", 'T', ' '), 12, 8) || '.000'\n ELSE \"UpdatedAt\"\n END;\n\n-- Update TotpCodes table (CreatedAt, UpdatedAt)\nUPDATE \"TotpCodes\" SET \"CreatedAt\" =\n CASE\n WHEN \"CreatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9] [0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9][0-9][0-9]'\n THEN \"CreatedAt\"\n WHEN \"CreatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]T[0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9]*'\n THEN substr(\"CreatedAt\", 1, 10) || ' ' || substr(\"CreatedAt\", 12, 12)\n WHEN \"CreatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9][T ][0-9][0-9]:[0-9][0-9]:[0-9][0-9]*'\n THEN substr(\"CreatedAt\", 1, 10) || ' ' || substr(replace(\"CreatedAt\", 'T', ' '), 12, 8) || '.000'\n ELSE \"CreatedAt\"\n END;\n\nUPDATE \"TotpCodes\" SET \"UpdatedAt\" =\n CASE\n WHEN \"UpdatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9] [0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9][0-9][0-9]'\n THEN \"UpdatedAt\"\n WHEN \"UpdatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]T[0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9]*'\n THEN substr(\"UpdatedAt\", 1, 10) || ' ' || substr(\"UpdatedAt\", 12, 12)\n WHEN \"UpdatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9][T ][0-9][0-9]:[0-9][0-9]:[0-9][0-9]*'\n THEN substr(\"UpdatedAt\", 1, 10) || ' ' || substr(replace(\"UpdatedAt\", 'T', ' '), 12, 8) || '.000'\n ELSE \"UpdatedAt\"\n END;\n\n-- =====================================================================================\n-- End of Date Format Normalization Migration\n-- =====================================================================================\n\n-- Recreate indexes\nCREATE INDEX \"IX_Credentials_AliasId\" ON \"Credentials\" (\"AliasId\");\nCREATE INDEX \"IX_Credentials_ServiceId\" ON \"Credentials\" (\"ServiceId\");\nCREATE INDEX \"IX_Attachments_CredentialId\" ON \"Attachments\" (\"CredentialId\");\nCREATE INDEX \"IX_Passwords_CredentialId\" ON \"Passwords\" (\"CredentialId\");\nCREATE INDEX \"IX_TotpCodes_CredentialId\" ON \"TotpCodes\" (\"CredentialId\");\n\n-- Clean up temp tables\nDROP TABLE \"__EFMigrationsHistory_temp\";\nDROP TABLE \"Aliases_temp\";\nDROP TABLE \"Services_temp\";\nDROP TABLE \"EncryptionKeys_temp\";\nDROP TABLE \"Settings_temp\";\nDROP TABLE \"Credentials_temp\";\nDROP TABLE \"Attachments_temp\";\nDROP TABLE \"Passwords_temp\";\nDROP TABLE \"TotpCodes_temp\";\n\nPRAGMA foreign_keys = ON;\n\n\nCREATE TABLE \"Passkeys\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_Passkeys\" PRIMARY KEY,\n \"RpId\" TEXT COLLATE NOCASE NOT NULL,\n \"UserHandle\" BLOB NOT NULL,\n \"PublicKey\" TEXT NOT NULL,\n \"PrivateKey\" TEXT NOT NULL,\n \"PrfKey\" BLOB NULL,\n \"DisplayName\" TEXT NOT NULL,\n \"AdditionalData\" BLOB NULL,\n \"CredentialId\" TEXT NOT NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"UpdatedAt\" TEXT NOT NULL,\n \"IsDeleted\" INTEGER NOT NULL,\n CONSTRAINT \"FK_Passkeys_Credentials_CredentialId\" FOREIGN KEY (\"CredentialId\") REFERENCES \"Credentials\" (\"Id\") ON DELETE CASCADE\n);\n\nCREATE INDEX \"IX_Passkeys_CredentialId\" ON \"Passkeys\" (\"CredentialId\");\n\nCREATE INDEX \"IX_Passkeys_RpId\" ON \"Passkeys\" (\"RpId\");\n\nINSERT INTO \"__EFMigrationsHistory\" (\"MigrationId\", \"ProductVersion\")\nVALUES ('20251014122838_1.6.0-AddPasskeys', '9.0.4');\n\nALTER TABLE \"TotpCodes\" RENAME COLUMN \"CredentialId\" TO \"ItemId\";\n\nDROP INDEX IF EXISTS \"IX_TotpCodes_CredentialId\";\n\nCREATE INDEX IF NOT EXISTS \"IX_TotpCodes_ItemId\" ON \"TotpCodes\" (\"ItemId\");\n\nALTER TABLE \"Passkeys\" RENAME COLUMN \"CredentialId\" TO \"ItemId\";\n\nDROP INDEX IF EXISTS \"IX_Passkeys_CredentialId\";\n\nCREATE INDEX IF NOT EXISTS \"IX_Passkeys_ItemId\" ON \"Passkeys\" (\"ItemId\");\n\nALTER TABLE \"Attachments\" RENAME COLUMN \"CredentialId\" TO \"ItemId\";\n\nDROP INDEX IF EXISTS \"IX_Attachments_CredentialId\";\n\nCREATE INDEX IF NOT EXISTS \"IX_Attachments_ItemId\" ON \"Attachments\" (\"ItemId\");\n\nCREATE TABLE \"FieldDefinitions\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_FieldDefinitions\" PRIMARY KEY,\n \"FieldType\" TEXT NOT NULL,\n \"Label\" TEXT NOT NULL,\n \"IsMultiValue\" INTEGER NOT NULL,\n \"IsHidden\" INTEGER NOT NULL,\n \"EnableHistory\" INTEGER NOT NULL,\n \"Weight\" INTEGER NOT NULL,\n \"ApplicableToTypes\" TEXT NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"UpdatedAt\" TEXT NOT NULL,\n \"IsDeleted\" INTEGER NOT NULL\n);\n\nCREATE TABLE \"Folders\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_Folders\" PRIMARY KEY,\n \"Name\" TEXT NOT NULL,\n \"ParentFolderId\" TEXT NULL,\n \"Weight\" INTEGER NOT NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"UpdatedAt\" TEXT NOT NULL,\n \"IsDeleted\" INTEGER NOT NULL,\n CONSTRAINT \"FK_Folders_Folders_ParentFolderId\" FOREIGN KEY (\"ParentFolderId\") REFERENCES \"Folders\" (\"Id\") ON DELETE CASCADE\n);\n\nCREATE TABLE \"Logos\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_Logos\" PRIMARY KEY,\n \"Source\" TEXT NOT NULL,\n \"FileData\" BLOB NULL,\n \"MimeType\" TEXT NULL,\n \"FetchedAt\" TEXT NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"UpdatedAt\" TEXT NOT NULL,\n \"IsDeleted\" INTEGER NOT NULL\n);\n\nCREATE TABLE \"Tags\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_Tags\" PRIMARY KEY,\n \"Name\" TEXT NOT NULL,\n \"Color\" TEXT NULL,\n \"DisplayOrder\" INTEGER NOT NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"UpdatedAt\" TEXT NOT NULL,\n \"IsDeleted\" INTEGER NOT NULL\n);\n\nCREATE TABLE \"Items\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_Items\" PRIMARY KEY,\n \"Name\" TEXT NULL,\n \"ItemType\" TEXT NOT NULL,\n \"LogoId\" TEXT NULL,\n \"DeletedAt\" TEXT NULL,\n \"FolderId\" TEXT NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"UpdatedAt\" TEXT NOT NULL,\n \"IsDeleted\" INTEGER NOT NULL,\n CONSTRAINT \"FK_Items_Folders_FolderId\" FOREIGN KEY (\"FolderId\") REFERENCES \"Folders\" (\"Id\") ON DELETE SET NULL,\n CONSTRAINT \"FK_Items_Logos_LogoId\" FOREIGN KEY (\"LogoId\") REFERENCES \"Logos\" (\"Id\") ON DELETE SET NULL\n);\n\nCREATE TABLE \"FieldHistories\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_FieldHistories\" PRIMARY KEY,\n \"ItemId\" TEXT NOT NULL,\n \"FieldDefinitionId\" TEXT NULL,\n \"FieldKey\" TEXT NULL,\n \"ValueSnapshot\" TEXT NOT NULL,\n \"ChangedAt\" TEXT NOT NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"UpdatedAt\" TEXT NOT NULL,\n \"IsDeleted\" INTEGER NOT NULL,\n CONSTRAINT \"FK_FieldHistories_FieldDefinitions_FieldDefinitionId\" FOREIGN KEY (\"FieldDefinitionId\") REFERENCES \"FieldDefinitions\" (\"Id\") ON DELETE CASCADE,\n CONSTRAINT \"FK_FieldHistories_Items_ItemId\" FOREIGN KEY (\"ItemId\") REFERENCES \"Items\" (\"Id\") ON DELETE CASCADE\n);\n\nCREATE TABLE \"FieldValues\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_FieldValues\" PRIMARY KEY,\n \"ItemId\" TEXT NOT NULL,\n \"FieldDefinitionId\" TEXT NULL,\n \"FieldKey\" TEXT NULL,\n \"Value\" TEXT NULL,\n \"Weight\" INTEGER NOT NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"UpdatedAt\" TEXT NOT NULL,\n \"IsDeleted\" INTEGER NOT NULL,\n CONSTRAINT \"FK_FieldValues_FieldDefinitions_FieldDefinitionId\" FOREIGN KEY (\"FieldDefinitionId\") REFERENCES \"FieldDefinitions\" (\"Id\") ON DELETE CASCADE,\n CONSTRAINT \"FK_FieldValues_Items_ItemId\" FOREIGN KEY (\"ItemId\") REFERENCES \"Items\" (\"Id\") ON DELETE CASCADE\n);\n\nCREATE TABLE \"ItemTags\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_ItemTags\" PRIMARY KEY,\n \"ItemId\" TEXT NOT NULL,\n \"TagId\" TEXT NOT NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"UpdatedAt\" TEXT NOT NULL,\n \"IsDeleted\" INTEGER NOT NULL,\n CONSTRAINT \"FK_ItemTags_Items_ItemId\" FOREIGN KEY (\"ItemId\") REFERENCES \"Items\" (\"Id\") ON DELETE CASCADE,\n CONSTRAINT \"FK_ItemTags_Tags_TagId\" FOREIGN KEY (\"TagId\") REFERENCES \"Tags\" (\"Id\") ON DELETE CASCADE\n);\n\nCREATE INDEX \"IX_FieldHistories_FieldDefinitionId\" ON \"FieldHistories\" (\"FieldDefinitionId\");\n\nCREATE INDEX \"IX_FieldHistories_ItemId\" ON \"FieldHistories\" (\"ItemId\");\n\nCREATE INDEX \"IX_FieldValues_FieldDefinitionId\" ON \"FieldValues\" (\"FieldDefinitionId\");\n\nCREATE INDEX \"IX_FieldValues_FieldKey\" ON \"FieldValues\" (\"FieldKey\");\n\nCREATE INDEX \"IX_FieldValues_ItemId\" ON \"FieldValues\" (\"ItemId\");\n\nCREATE INDEX \"IX_FieldValues_ItemId_FieldDefinitionId_Weight\" ON \"FieldValues\" (\"ItemId\", \"FieldDefinitionId\", \"Weight\");\n\nCREATE INDEX \"IX_FieldValues_ItemId_FieldKey\" ON \"FieldValues\" (\"ItemId\", \"FieldKey\");\n\nCREATE INDEX \"IX_Folders_ParentFolderId\" ON \"Folders\" (\"ParentFolderId\");\n\nCREATE INDEX \"IX_Items_FolderId\" ON \"Items\" (\"FolderId\");\n\nCREATE INDEX \"IX_Items_LogoId\" ON \"Items\" (\"LogoId\");\n\nCREATE INDEX \"IX_ItemTags_ItemId\" ON \"ItemTags\" (\"ItemId\");\n\nCREATE UNIQUE INDEX \"IX_ItemTags_ItemId_TagId\" ON \"ItemTags\" (\"ItemId\", \"TagId\");\n\nCREATE INDEX \"IX_ItemTags_TagId\" ON \"ItemTags\" (\"TagId\");\n\nCREATE UNIQUE INDEX \"IX_Logos_Source\" ON \"Logos\" (\"Source\");\n\nCREATE INDEX \"IX_Tags_Name\" ON \"Tags\" (\"Name\");\n\n\n INSERT INTO Items (Id, Name, ItemType, LogoId, FolderId, CreatedAt, UpdatedAt, IsDeleted)\n SELECT\n c.Id,\n s.Name AS Name,\n CASE\n WHEN a.Id IS NOT NULL AND (\n (a.FirstName IS NOT NULL AND a.FirstName != '') OR\n (a.LastName IS NOT NULL AND a.LastName != '') OR\n (a.Gender IS NOT NULL AND a.Gender != '') OR\n (a.BirthDate IS NOT NULL AND a.BirthDate != '' AND a.BirthDate NOT LIKE '0001-%')\n ) THEN 'Alias'\n ELSE 'Login'\n END AS ItemType,\n NULL AS LogoId,\n NULL AS FolderId,\n c.CreatedAt,\n c.UpdatedAt,\n c.IsDeleted\n FROM Credentials c\n LEFT JOIN Services s ON s.Id = c.ServiceId\n LEFT JOIN Aliases a ON a.Id = c.AliasId;\n \n\n\n INSERT INTO Logos (Id, Source, FileData, MimeType, FetchedAt, CreatedAt, UpdatedAt, IsDeleted)\n SELECT\n UPPER(SUBSTR(hex(randomblob(4)), 1, 8) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(6)), 1, 12)) AS Id,\n -- Extract and normalize hostname: remove protocol, path, lowercase, and www. prefix\n REPLACE(\n LOWER(\n SUBSTR(\n CASE\n WHEN s.Url LIKE 'https://%' THEN SUBSTR(s.Url, 9)\n WHEN s.Url LIKE 'http://%' THEN SUBSTR(s.Url, 8)\n ELSE s.Url\n END,\n 1,\n CASE\n WHEN INSTR(\n CASE\n WHEN s.Url LIKE 'https://%' THEN SUBSTR(s.Url, 9)\n WHEN s.Url LIKE 'http://%' THEN SUBSTR(s.Url, 8)\n ELSE s.Url\n END, '/') > 0\n THEN INSTR(\n CASE\n WHEN s.Url LIKE 'https://%' THEN SUBSTR(s.Url, 9)\n WHEN s.Url LIKE 'http://%' THEN SUBSTR(s.Url, 8)\n ELSE s.Url\n END, '/') - 1\n ELSE LENGTH(\n CASE\n WHEN s.Url LIKE 'https://%' THEN SUBSTR(s.Url, 9)\n WHEN s.Url LIKE 'http://%' THEN SUBSTR(s.Url, 8)\n ELSE s.Url\n END)\n END\n )\n ),\n 'www.', ''\n ) AS Source,\n s.Logo AS FileData,\n 'image/png' AS MimeType,\n NULL AS FetchedAt,\n MIN(s.CreatedAt) AS CreatedAt,\n MAX(s.UpdatedAt) AS UpdatedAt,\n 0 AS IsDeleted\n FROM Services s\n WHERE s.Logo IS NOT NULL AND s.Url IS NOT NULL AND s.Url != ''\n GROUP BY REPLACE(\n LOWER(\n SUBSTR(\n CASE\n WHEN s.Url LIKE 'https://%' THEN SUBSTR(s.Url, 9)\n WHEN s.Url LIKE 'http://%' THEN SUBSTR(s.Url, 8)\n ELSE s.Url\n END,\n 1,\n CASE\n WHEN INSTR(\n CASE\n WHEN s.Url LIKE 'https://%' THEN SUBSTR(s.Url, 9)\n WHEN s.Url LIKE 'http://%' THEN SUBSTR(s.Url, 8)\n ELSE s.Url\n END, '/') > 0\n THEN INSTR(\n CASE\n WHEN s.Url LIKE 'https://%' THEN SUBSTR(s.Url, 9)\n WHEN s.Url LIKE 'http://%' THEN SUBSTR(s.Url, 8)\n ELSE s.Url\n END, '/') - 1\n ELSE LENGTH(\n CASE\n WHEN s.Url LIKE 'https://%' THEN SUBSTR(s.Url, 9)\n WHEN s.Url LIKE 'http://%' THEN SUBSTR(s.Url, 8)\n ELSE s.Url\n END)\n END\n )\n ),\n 'www.', ''\n );\n \n\n\n UPDATE Items\n SET LogoId = (\n SELECT l.Id FROM Logos l\n INNER JOIN Services s ON REPLACE(\n LOWER(\n SUBSTR(\n CASE\n WHEN s.Url LIKE 'https://%' THEN SUBSTR(s.Url, 9)\n WHEN s.Url LIKE 'http://%' THEN SUBSTR(s.Url, 8)\n ELSE s.Url\n END,\n 1,\n CASE\n WHEN INSTR(\n CASE\n WHEN s.Url LIKE 'https://%' THEN SUBSTR(s.Url, 9)\n WHEN s.Url LIKE 'http://%' THEN SUBSTR(s.Url, 8)\n ELSE s.Url\n END, '/') > 0\n THEN INSTR(\n CASE\n WHEN s.Url LIKE 'https://%' THEN SUBSTR(s.Url, 9)\n WHEN s.Url LIKE 'http://%' THEN SUBSTR(s.Url, 8)\n ELSE s.Url\n END, '/') - 1\n ELSE LENGTH(\n CASE\n WHEN s.Url LIKE 'https://%' THEN SUBSTR(s.Url, 9)\n WHEN s.Url LIKE 'http://%' THEN SUBSTR(s.Url, 8)\n ELSE s.Url\n END)\n END\n )\n ),\n 'www.', ''\n ) = l.Source\n INNER JOIN Credentials c ON c.ServiceId = s.Id\n WHERE c.Id = Items.Id\n LIMIT 1\n )\n WHERE EXISTS (\n SELECT 1 FROM Credentials c\n INNER JOIN Services s ON s.Id = c.ServiceId\n WHERE c.Id = Items.Id AND s.Logo IS NOT NULL\n );\n \n\n\n INSERT INTO FieldValues (Id, ItemId, FieldDefinitionId, FieldKey, Value, Weight, CreatedAt, UpdatedAt, IsDeleted)\n SELECT\n UPPER(SUBSTR(hex(randomblob(4)), 1, 8) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(6)), 1, 12)) AS Id,\n c.Id AS ItemId,\n NULL AS FieldDefinitionId,\n 'login.url' AS FieldKey,\n s.Url AS Value,\n 0 AS Weight,\n s.UpdatedAt AS CreatedAt,\n s.UpdatedAt AS UpdatedAt,\n 0 AS IsDeleted\n FROM Credentials c\n INNER JOIN Services s ON s.Id = c.ServiceId\n WHERE s.Url IS NOT NULL AND s.Url != '';\n \n\n\n INSERT INTO FieldValues (Id, ItemId, FieldDefinitionId, FieldKey, Value, Weight, CreatedAt, UpdatedAt, IsDeleted)\n SELECT\n UPPER(SUBSTR(hex(randomblob(4)), 1, 8) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(6)), 1, 12)) AS Id,\n c.Id AS ItemId,\n NULL AS FieldDefinitionId,\n 'login.username' AS FieldKey,\n c.Username AS Value,\n 0 AS Weight,\n c.UpdatedAt AS CreatedAt,\n c.UpdatedAt AS UpdatedAt,\n 0 AS IsDeleted\n FROM Credentials c\n WHERE c.Username IS NOT NULL AND c.Username != '';\n \n\n\n INSERT INTO FieldValues (Id, ItemId, FieldDefinitionId, FieldKey, Value, Weight, CreatedAt, UpdatedAt, IsDeleted)\n SELECT\n UPPER(SUBSTR(hex(randomblob(4)), 1, 8) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(6)), 1, 12)) AS Id,\n c.Id AS ItemId,\n NULL AS FieldDefinitionId,\n 'login.notes' AS FieldKey,\n c.Notes AS Value,\n 0 AS Weight,\n c.UpdatedAt AS CreatedAt,\n c.UpdatedAt AS UpdatedAt,\n 0 AS IsDeleted\n FROM Credentials c\n WHERE c.Notes IS NOT NULL AND c.Notes != '';\n \n\n\n INSERT INTO FieldValues (Id, ItemId, FieldDefinitionId, FieldKey, Value, Weight, CreatedAt, UpdatedAt, IsDeleted)\n SELECT\n UPPER(SUBSTR(hex(randomblob(4)), 1, 8) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(6)), 1, 12)) AS Id,\n p.CredentialId AS ItemId,\n NULL AS FieldDefinitionId,\n 'login.password' AS FieldKey,\n p.Value AS Value,\n 0 AS Weight,\n p.UpdatedAt AS CreatedAt,\n p.UpdatedAt AS UpdatedAt,\n 0 AS IsDeleted\n FROM Passwords p\n INNER JOIN (\n SELECT CredentialId, MAX(UpdatedAt) AS MaxUpdated, MAX(Id) AS MaxId\n FROM Passwords\n WHERE IsDeleted = 0\n GROUP BY CredentialId\n ) pm ON p.CredentialId = pm.CredentialId AND p.UpdatedAt = pm.MaxUpdated AND p.Id = pm.MaxId\n WHERE p.IsDeleted = 0;\n \n\n\n INSERT INTO FieldValues (Id, ItemId, FieldDefinitionId, FieldKey, Value, Weight, CreatedAt, UpdatedAt, IsDeleted)\n SELECT\n UPPER(SUBSTR(hex(randomblob(4)), 1, 8) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(6)), 1, 12)) AS Id,\n c.Id AS ItemId,\n NULL AS FieldDefinitionId,\n 'login.email' AS FieldKey,\n a.Email AS Value,\n 0 AS Weight,\n a.UpdatedAt AS CreatedAt,\n a.UpdatedAt AS UpdatedAt,\n 0 AS IsDeleted\n FROM Credentials c\n INNER JOIN Aliases a ON a.Id = c.AliasId\n WHERE a.Email IS NOT NULL AND a.Email != '';\n \n\n\n INSERT INTO FieldValues (Id, ItemId, FieldDefinitionId, FieldKey, Value, Weight, CreatedAt, UpdatedAt, IsDeleted)\n SELECT\n UPPER(SUBSTR(hex(randomblob(4)), 1, 8) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(6)), 1, 12)) AS Id,\n c.Id AS ItemId,\n NULL AS FieldDefinitionId,\n 'alias.first_name' AS FieldKey,\n a.FirstName AS Value,\n 0 AS Weight,\n a.UpdatedAt AS CreatedAt,\n a.UpdatedAt AS UpdatedAt,\n 0 AS IsDeleted\n FROM Credentials c\n INNER JOIN Aliases a ON a.Id = c.AliasId\n WHERE a.FirstName IS NOT NULL AND a.FirstName != '';\n \n\n\n INSERT INTO FieldValues (Id, ItemId, FieldDefinitionId, FieldKey, Value, Weight, CreatedAt, UpdatedAt, IsDeleted)\n SELECT\n UPPER(SUBSTR(hex(randomblob(4)), 1, 8) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(6)), 1, 12)) AS Id,\n c.Id AS ItemId,\n NULL AS FieldDefinitionId,\n 'alias.last_name' AS FieldKey,\n a.LastName AS Value,\n 0 AS Weight,\n a.UpdatedAt AS CreatedAt,\n a.UpdatedAt AS UpdatedAt,\n 0 AS IsDeleted\n FROM Credentials c\n INNER JOIN Aliases a ON a.Id = c.AliasId\n WHERE a.LastName IS NOT NULL AND a.LastName != '';\n \n\n\n INSERT INTO FieldValues (Id, ItemId, FieldDefinitionId, FieldKey, Value, Weight, CreatedAt, UpdatedAt, IsDeleted)\n SELECT\n UPPER(SUBSTR(hex(randomblob(4)), 1, 8) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(6)), 1, 12)) AS Id,\n c.Id AS ItemId,\n NULL AS FieldDefinitionId,\n 'alias.gender' AS FieldKey,\n a.Gender AS Value,\n 0 AS Weight,\n a.UpdatedAt AS CreatedAt,\n a.UpdatedAt AS UpdatedAt,\n 0 AS IsDeleted\n FROM Credentials c\n INNER JOIN Aliases a ON a.Id = c.AliasId\n WHERE a.Gender IS NOT NULL AND a.Gender != '';\n \n\n\n INSERT INTO FieldValues (Id, ItemId, FieldDefinitionId, FieldKey, Value, Weight, CreatedAt, UpdatedAt, IsDeleted)\n SELECT\n UPPER(SUBSTR(hex(randomblob(4)), 1, 8) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(6)), 1, 12)) AS Id,\n c.Id AS ItemId,\n NULL AS FieldDefinitionId,\n 'alias.birthdate' AS FieldKey,\n SUBSTR(a.BirthDate, 1, 10) AS Value,\n 0 AS Weight,\n a.UpdatedAt AS CreatedAt,\n a.UpdatedAt AS UpdatedAt,\n 0 AS IsDeleted\n FROM Credentials c\n INNER JOIN Aliases a ON a.Id = c.AliasId\n WHERE a.BirthDate IS NOT NULL AND a.BirthDate != '' AND a.BirthDate NOT LIKE '0001-%';\n \n\nDROP TABLE \"Passwords\";\n\nDROP TABLE \"Credentials\";\n\nDROP TABLE \"Aliases\";\n\nDROP TABLE \"Services\";\n\nCREATE TABLE \"ef_temp_Attachments\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_Attachments\" PRIMARY KEY,\n \"Blob\" BLOB NOT NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"Filename\" TEXT NOT NULL,\n \"IsDeleted\" INTEGER NOT NULL,\n \"ItemId\" TEXT NOT NULL,\n \"UpdatedAt\" TEXT NOT NULL,\n CONSTRAINT \"FK_Attachments_Items_ItemId\" FOREIGN KEY (\"ItemId\") REFERENCES \"Items\" (\"Id\") ON DELETE CASCADE\n);\n\nINSERT INTO \"ef_temp_Attachments\" (\"Id\", \"Blob\", \"CreatedAt\", \"Filename\", \"IsDeleted\", \"ItemId\", \"UpdatedAt\")\nSELECT \"Id\", \"Blob\", \"CreatedAt\", \"Filename\", \"IsDeleted\", \"ItemId\", \"UpdatedAt\"\nFROM \"Attachments\";\n\nCREATE TABLE \"ef_temp_Passkeys\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_Passkeys\" PRIMARY KEY,\n \"AdditionalData\" BLOB NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"DisplayName\" TEXT NOT NULL,\n \"IsDeleted\" INTEGER NOT NULL,\n \"ItemId\" TEXT NOT NULL,\n \"PrfKey\" BLOB NULL,\n \"PrivateKey\" TEXT NOT NULL,\n \"PublicKey\" TEXT NOT NULL,\n \"RpId\" TEXT COLLATE NOCASE NOT NULL,\n \"UpdatedAt\" TEXT NOT NULL,\n \"UserHandle\" BLOB NOT NULL,\n CONSTRAINT \"FK_Passkeys_Items_ItemId\" FOREIGN KEY (\"ItemId\") REFERENCES \"Items\" (\"Id\") ON DELETE CASCADE\n);\n\nINSERT INTO \"ef_temp_Passkeys\" (\"Id\", \"AdditionalData\", \"CreatedAt\", \"DisplayName\", \"IsDeleted\", \"ItemId\", \"PrfKey\", \"PrivateKey\", \"PublicKey\", \"RpId\", \"UpdatedAt\", \"UserHandle\")\nSELECT \"Id\", \"AdditionalData\", \"CreatedAt\", \"DisplayName\", \"IsDeleted\", \"ItemId\", \"PrfKey\", \"PrivateKey\", \"PublicKey\", \"RpId\", \"UpdatedAt\", \"UserHandle\"\nFROM \"Passkeys\";\n\nCREATE TABLE \"ef_temp_TotpCodes\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_TotpCodes\" PRIMARY KEY,\n \"CreatedAt\" TEXT NOT NULL,\n \"IsDeleted\" INTEGER NOT NULL,\n \"ItemId\" TEXT NOT NULL,\n \"Name\" TEXT NOT NULL,\n \"SecretKey\" TEXT NOT NULL,\n \"UpdatedAt\" TEXT NOT NULL,\n CONSTRAINT \"FK_TotpCodes_Items_ItemId\" FOREIGN KEY (\"ItemId\") REFERENCES \"Items\" (\"Id\") ON DELETE CASCADE\n);\n\nINSERT INTO \"ef_temp_TotpCodes\" (\"Id\", \"CreatedAt\", \"IsDeleted\", \"ItemId\", \"Name\", \"SecretKey\", \"UpdatedAt\")\nSELECT \"Id\", \"CreatedAt\", \"IsDeleted\", \"ItemId\", \"Name\", \"SecretKey\", \"UpdatedAt\"\nFROM \"TotpCodes\";\n\nCOMMIT;\n\nPRAGMA foreign_keys = 0;\n\nBEGIN TRANSACTION;\nDROP TABLE \"Attachments\";\n\nALTER TABLE \"ef_temp_Attachments\" RENAME TO \"Attachments\";\n\nDROP TABLE \"Passkeys\";\n\nALTER TABLE \"ef_temp_Passkeys\" RENAME TO \"Passkeys\";\n\nDROP TABLE \"TotpCodes\";\n\nALTER TABLE \"ef_temp_TotpCodes\" RENAME TO \"TotpCodes\";\n\nCOMMIT;\n\nPRAGMA foreign_keys = 1;\n\nBEGIN TRANSACTION;\nCREATE INDEX \"IX_Attachments_ItemId\" ON \"Attachments\" (\"ItemId\");\n\nCREATE INDEX \"IX_Passkeys_ItemId\" ON \"Passkeys\" (\"ItemId\");\n\nCREATE INDEX \"IX_Passkeys_RpId\" ON \"Passkeys\" (\"RpId\");\n\nCREATE INDEX \"IX_TotpCodes_ItemId\" ON \"TotpCodes\" (\"ItemId\");\n\nCOMMIT;\n\nINSERT INTO \"__EFMigrationsHistory\" (\"MigrationId\", \"ProductVersion\")\nVALUES ('20251213111207_1.7.0-FieldBasedDataModelUpdate', '9.0.4');\n"; +declare const COMPLETE_SCHEMA_SQL = "\n\uFEFFCREATE TABLE IF NOT EXISTS \"__EFMigrationsHistory\" (\n \"MigrationId\" TEXT NOT NULL CONSTRAINT \"PK___EFMigrationsHistory\" PRIMARY KEY,\n \"ProductVersion\" TEXT NOT NULL\n);\n\nBEGIN TRANSACTION;\nCREATE TABLE \"Aliases\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_Aliases\" PRIMARY KEY,\n \"Gender\" VARCHAR NULL,\n \"FirstName\" VARCHAR NULL,\n \"LastName\" VARCHAR NULL,\n \"NickName\" VARCHAR NULL,\n \"BirthDate\" TEXT NOT NULL,\n \"AddressStreet\" VARCHAR NULL,\n \"AddressCity\" VARCHAR NULL,\n \"AddressState\" VARCHAR NULL,\n \"AddressZipCode\" VARCHAR NULL,\n \"AddressCountry\" VARCHAR NULL,\n \"Hobbies\" TEXT NULL,\n \"EmailPrefix\" TEXT NULL,\n \"PhoneMobile\" TEXT NULL,\n \"BankAccountIBAN\" TEXT NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"UpdatedAt\" TEXT NOT NULL\n);\n\nCREATE TABLE \"Services\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_Services\" PRIMARY KEY,\n \"Name\" TEXT NULL,\n \"Url\" TEXT NULL,\n \"Logo\" BLOB NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"UpdatedAt\" TEXT NOT NULL\n);\n\nCREATE TABLE \"Credentials\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_Credentials\" PRIMARY KEY,\n \"AliasId\" TEXT NOT NULL,\n \"Notes\" TEXT NULL,\n \"Username\" TEXT NOT NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"UpdatedAt\" TEXT NOT NULL,\n \"ServiceId\" TEXT NOT NULL,\n CONSTRAINT \"FK_Credentials_Aliases_AliasId\" FOREIGN KEY (\"AliasId\") REFERENCES \"Aliases\" (\"Id\") ON DELETE CASCADE,\n CONSTRAINT \"FK_Credentials_Services_ServiceId\" FOREIGN KEY (\"ServiceId\") REFERENCES \"Services\" (\"Id\") ON DELETE CASCADE\n);\n\nCREATE TABLE \"Attachment\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_Attachment\" PRIMARY KEY,\n \"Filename\" TEXT NOT NULL,\n \"Blob\" BLOB NOT NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"UpdatedAt\" TEXT NOT NULL,\n \"CredentialId\" TEXT NOT NULL,\n CONSTRAINT \"FK_Attachment_Credentials_CredentialId\" FOREIGN KEY (\"CredentialId\") REFERENCES \"Credentials\" (\"Id\") ON DELETE CASCADE\n);\n\nCREATE TABLE \"Passwords\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_Passwords\" PRIMARY KEY,\n \"Value\" TEXT NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"UpdatedAt\" TEXT NOT NULL,\n \"CredentialId\" TEXT NOT NULL,\n CONSTRAINT \"FK_Passwords_Credentials_CredentialId\" FOREIGN KEY (\"CredentialId\") REFERENCES \"Credentials\" (\"Id\") ON DELETE CASCADE\n);\n\nCREATE INDEX \"IX_Attachment_CredentialId\" ON \"Attachment\" (\"CredentialId\");\n\nCREATE INDEX \"IX_Credentials_AliasId\" ON \"Credentials\" (\"AliasId\");\n\nCREATE INDEX \"IX_Credentials_ServiceId\" ON \"Credentials\" (\"ServiceId\");\n\nCREATE INDEX \"IX_Passwords_CredentialId\" ON \"Passwords\" (\"CredentialId\");\n\nINSERT INTO \"__EFMigrationsHistory\" (\"MigrationId\", \"ProductVersion\")\nVALUES ('20240708094944_1.0.0-InitialMigration', '9.0.4');\n\nINSERT INTO \"__EFMigrationsHistory\" (\"MigrationId\", \"ProductVersion\")\nVALUES ('20240708224522_1.0.1-EmptyTestMigration', '9.0.4');\n\nALTER TABLE \"Aliases\" RENAME COLUMN \"EmailPrefix\" TO \"Email\";\n\nINSERT INTO \"__EFMigrationsHistory\" (\"MigrationId\", \"ProductVersion\")\nVALUES ('20240711204207_1.0.2-ChangeEmailColumn', '9.0.4');\n\nCREATE TABLE \"EncryptionKeys\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_EncryptionKeys\" PRIMARY KEY,\n \"PublicKey\" TEXT NOT NULL,\n \"PrivateKey\" TEXT NOT NULL,\n \"IsPrimary\" INTEGER NOT NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"UpdatedAt\" TEXT NOT NULL\n);\n\nINSERT INTO \"__EFMigrationsHistory\" (\"MigrationId\", \"ProductVersion\")\nVALUES ('20240729105618_1.1.0-AddPkiTables', '9.0.4');\n\nCREATE TABLE \"Settings\" (\n \"Key\" TEXT NOT NULL CONSTRAINT \"PK_Settings\" PRIMARY KEY,\n \"Value\" TEXT NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"UpdatedAt\" TEXT NOT NULL\n);\n\nINSERT INTO \"__EFMigrationsHistory\" (\"MigrationId\", \"ProductVersion\")\nVALUES ('20240805073413_1.2.0-AddSettingsTable', '9.0.4');\n\nCREATE TABLE \"ef_temp_Aliases\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_Aliases\" PRIMARY KEY,\n \"BirthDate\" TEXT NOT NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"Email\" TEXT NULL,\n \"FirstName\" VARCHAR NULL,\n \"Gender\" VARCHAR NULL,\n \"LastName\" VARCHAR NULL,\n \"NickName\" VARCHAR NULL,\n \"UpdatedAt\" TEXT NOT NULL\n);\n\nINSERT INTO \"ef_temp_Aliases\" (\"Id\", \"BirthDate\", \"CreatedAt\", \"Email\", \"FirstName\", \"Gender\", \"LastName\", \"NickName\", \"UpdatedAt\")\nSELECT \"Id\", \"BirthDate\", \"CreatedAt\", \"Email\", \"FirstName\", \"Gender\", \"LastName\", \"NickName\", \"UpdatedAt\"\nFROM \"Aliases\";\n\nCOMMIT;\n\nPRAGMA foreign_keys = 0;\n\nBEGIN TRANSACTION;\nDROP TABLE \"Aliases\";\n\nALTER TABLE \"ef_temp_Aliases\" RENAME TO \"Aliases\";\n\nCOMMIT;\n\nPRAGMA foreign_keys = 1;\n\nINSERT INTO \"__EFMigrationsHistory\" (\"MigrationId\", \"ProductVersion\")\nVALUES ('20240805122422_1.3.0-UpdateIdentityStructure', '9.0.4');\n\nBEGIN TRANSACTION;\nCREATE TABLE \"ef_temp_Credentials\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_Credentials\" PRIMARY KEY,\n \"AliasId\" TEXT NOT NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"Notes\" TEXT NULL,\n \"ServiceId\" TEXT NOT NULL,\n \"UpdatedAt\" TEXT NOT NULL,\n \"Username\" TEXT NULL,\n CONSTRAINT \"FK_Credentials_Aliases_AliasId\" FOREIGN KEY (\"AliasId\") REFERENCES \"Aliases\" (\"Id\") ON DELETE CASCADE,\n CONSTRAINT \"FK_Credentials_Services_ServiceId\" FOREIGN KEY (\"ServiceId\") REFERENCES \"Services\" (\"Id\") ON DELETE CASCADE\n);\n\nINSERT INTO \"ef_temp_Credentials\" (\"Id\", \"AliasId\", \"CreatedAt\", \"Notes\", \"ServiceId\", \"UpdatedAt\", \"Username\")\nSELECT \"Id\", \"AliasId\", \"CreatedAt\", \"Notes\", \"ServiceId\", \"UpdatedAt\", \"Username\"\nFROM \"Credentials\";\n\nCOMMIT;\n\nPRAGMA foreign_keys = 0;\n\nBEGIN TRANSACTION;\nDROP TABLE \"Credentials\";\n\nALTER TABLE \"ef_temp_Credentials\" RENAME TO \"Credentials\";\n\nCOMMIT;\n\nPRAGMA foreign_keys = 1;\n\nBEGIN TRANSACTION;\nCREATE INDEX \"IX_Credentials_AliasId\" ON \"Credentials\" (\"AliasId\");\n\nCREATE INDEX \"IX_Credentials_ServiceId\" ON \"Credentials\" (\"ServiceId\");\n\nCOMMIT;\n\nINSERT INTO \"__EFMigrationsHistory\" (\"MigrationId\", \"ProductVersion\")\nVALUES ('20240812141727_1.3.1-MakeUsernameOptional', '9.0.4');\n\nBEGIN TRANSACTION;\nALTER TABLE \"Settings\" ADD \"IsDeleted\" INTEGER NOT NULL DEFAULT 0;\n\nALTER TABLE \"Services\" ADD \"IsDeleted\" INTEGER NOT NULL DEFAULT 0;\n\nALTER TABLE \"Passwords\" ADD \"IsDeleted\" INTEGER NOT NULL DEFAULT 0;\n\nALTER TABLE \"EncryptionKeys\" ADD \"IsDeleted\" INTEGER NOT NULL DEFAULT 0;\n\nALTER TABLE \"Credentials\" ADD \"IsDeleted\" INTEGER NOT NULL DEFAULT 0;\n\nALTER TABLE \"Attachment\" ADD \"IsDeleted\" INTEGER NOT NULL DEFAULT 0;\n\nALTER TABLE \"Aliases\" ADD \"IsDeleted\" INTEGER NOT NULL DEFAULT 0;\n\nINSERT INTO \"__EFMigrationsHistory\" (\"MigrationId\", \"ProductVersion\")\nVALUES ('20240916105320_1.4.0-AddSyncSupport', '9.0.4');\n\nALTER TABLE \"Attachment\" RENAME TO \"Attachments\";\n\nCREATE TABLE \"ef_temp_Attachments\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_Attachments\" PRIMARY KEY,\n \"Blob\" BLOB NOT NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"CredentialId\" TEXT NOT NULL,\n \"Filename\" TEXT NOT NULL,\n \"IsDeleted\" INTEGER NOT NULL,\n \"UpdatedAt\" TEXT NOT NULL,\n CONSTRAINT \"FK_Attachments_Credentials_CredentialId\" FOREIGN KEY (\"CredentialId\") REFERENCES \"Credentials\" (\"Id\") ON DELETE CASCADE\n);\n\nINSERT INTO \"ef_temp_Attachments\" (\"Id\", \"Blob\", \"CreatedAt\", \"CredentialId\", \"Filename\", \"IsDeleted\", \"UpdatedAt\")\nSELECT \"Id\", \"Blob\", \"CreatedAt\", \"CredentialId\", \"Filename\", \"IsDeleted\", \"UpdatedAt\"\nFROM \"Attachments\";\n\nCOMMIT;\n\nPRAGMA foreign_keys = 0;\n\nBEGIN TRANSACTION;\nDROP TABLE \"Attachments\";\n\nALTER TABLE \"ef_temp_Attachments\" RENAME TO \"Attachments\";\n\nCOMMIT;\n\nPRAGMA foreign_keys = 1;\n\nBEGIN TRANSACTION;\nCREATE INDEX \"IX_Attachments_CredentialId\" ON \"Attachments\" (\"CredentialId\");\n\nCOMMIT;\n\nINSERT INTO \"__EFMigrationsHistory\" (\"MigrationId\", \"ProductVersion\")\nVALUES ('20240917191243_1.4.1-RenameAttachmentsPlural', '9.0.4');\n\nBEGIN TRANSACTION;\nCREATE TABLE \"TotpCodes\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_TotpCodes\" PRIMARY KEY,\n \"Name\" TEXT NOT NULL,\n \"SecretKey\" TEXT NOT NULL,\n \"CredentialId\" TEXT NOT NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"UpdatedAt\" TEXT NOT NULL,\n \"IsDeleted\" INTEGER NOT NULL,\n CONSTRAINT \"FK_TotpCodes_Credentials_CredentialId\" FOREIGN KEY (\"CredentialId\") REFERENCES \"Credentials\" (\"Id\") ON DELETE CASCADE\n);\n\nCREATE INDEX \"IX_TotpCodes_CredentialId\" ON \"TotpCodes\" (\"CredentialId\");\n\nINSERT INTO \"__EFMigrationsHistory\" (\"MigrationId\", \"ProductVersion\")\nVALUES ('20250310131554_1.5.0-AddTotpCodes', '9.0.4');\n\n\nPRAGMA foreign_keys = OFF;\n\n-- Clean up any existing temp tables first\nDROP TABLE IF EXISTS \"__EFMigrationsHistory_temp\";\nDROP TABLE IF EXISTS \"Aliases_temp\";\nDROP TABLE IF EXISTS \"Services_temp\";\nDROP TABLE IF EXISTS \"EncryptionKeys_temp\";\nDROP TABLE IF EXISTS \"Settings_temp\";\nDROP TABLE IF EXISTS \"Credentials_temp\";\nDROP TABLE IF EXISTS \"Attachments_temp\";\nDROP TABLE IF EXISTS \"Passwords_temp\";\nDROP TABLE IF EXISTS \"TotpCodes_temp\";\n\n-- Create backup tables for all data\nCREATE TABLE \"__EFMigrationsHistory_temp\" AS SELECT * FROM \"__EFMigrationsHistory\";\nCREATE TABLE \"Aliases_temp\" AS SELECT * FROM \"Aliases\";\nCREATE TABLE \"Services_temp\" AS SELECT * FROM \"Services\";\nCREATE TABLE \"EncryptionKeys_temp\" AS SELECT * FROM \"EncryptionKeys\";\nCREATE TABLE \"Settings_temp\" AS SELECT * FROM \"Settings\";\nCREATE TABLE \"Credentials_temp\" AS SELECT * FROM \"Credentials\";\nCREATE TABLE \"Attachments_temp\" AS SELECT * FROM \"Attachments\";\nCREATE TABLE \"Passwords_temp\" AS SELECT * FROM \"Passwords\";\nCREATE TABLE \"TotpCodes_temp\" AS SELECT * FROM \"TotpCodes\";\n\n-- Delete orphaned records that do not have a valid FK to the credential object\nDELETE FROM \"Attachments_temp\" WHERE \"CredentialId\" NOT IN (SELECT \"Id\" FROM \"Credentials_temp\");\nDELETE FROM \"Passwords_temp\" WHERE \"CredentialId\" NOT IN (SELECT \"Id\" FROM \"Credentials_temp\");\nDELETE FROM \"TotpCodes_temp\" WHERE \"CredentialId\" NOT IN (SELECT \"Id\" FROM \"Credentials_temp\");\n\n-- Delete orphaned credentials that do not have valid FKs to alias or service objects\nDELETE FROM \"Credentials_temp\" WHERE \"AliasId\" NOT IN (SELECT \"Id\" FROM \"Aliases_temp\");\nDELETE FROM \"Credentials_temp\" WHERE \"ServiceId\" NOT IN (SELECT \"Id\" FROM \"Services_temp\");\n\n-- After cleaning credentials, clean dependent tables again in case we removed credentials\nDELETE FROM \"Attachments_temp\" WHERE \"CredentialId\" NOT IN (SELECT \"Id\" FROM \"Credentials_temp\");\nDELETE FROM \"Passwords_temp\" WHERE \"CredentialId\" NOT IN (SELECT \"Id\" FROM \"Credentials_temp\");\nDELETE FROM \"TotpCodes_temp\" WHERE \"CredentialId\" NOT IN (SELECT \"Id\" FROM \"Credentials_temp\");\n\n-- Drop all existing tables\nDROP TABLE \"TotpCodes\";\nDROP TABLE \"Passwords\";\nDROP TABLE \"Attachments\";\nDROP TABLE \"Credentials\";\nDROP TABLE \"Settings\";\nDROP TABLE \"EncryptionKeys\";\nDROP TABLE \"Services\";\nDROP TABLE \"Aliases\";\nDROP TABLE \"__EFMigrationsHistory\";\n\n-- Recreate tables with proper constraints (no dependencies first)\nCREATE TABLE \"__EFMigrationsHistory\" (\n \"MigrationId\" TEXT NOT NULL CONSTRAINT \"PK___EFMigrationsHistory\" PRIMARY KEY,\n \"ProductVersion\" TEXT NOT NULL\n);\n\nCREATE TABLE \"Aliases\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_Aliases\" PRIMARY KEY,\n \"BirthDate\" TEXT NOT NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"Email\" TEXT NULL,\n \"FirstName\" VARCHAR NULL,\n \"Gender\" VARCHAR NULL,\n \"LastName\" VARCHAR NULL,\n \"NickName\" VARCHAR NULL,\n \"UpdatedAt\" TEXT NOT NULL,\n \"IsDeleted\" INTEGER NOT NULL DEFAULT 0\n);\n\nCREATE TABLE \"Services\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_Services\" PRIMARY KEY,\n \"Name\" TEXT NULL,\n \"Url\" TEXT NULL,\n \"Logo\" BLOB NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"UpdatedAt\" TEXT NOT NULL,\n \"IsDeleted\" INTEGER NOT NULL DEFAULT 0\n);\n\nCREATE TABLE \"EncryptionKeys\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_EncryptionKeys\" PRIMARY KEY,\n \"PublicKey\" TEXT NOT NULL,\n \"PrivateKey\" TEXT NOT NULL,\n \"IsPrimary\" INTEGER NOT NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"UpdatedAt\" TEXT NOT NULL,\n \"IsDeleted\" INTEGER NOT NULL DEFAULT 0\n);\n\nCREATE TABLE \"Settings\" (\n \"Key\" TEXT NOT NULL CONSTRAINT \"PK_Settings\" PRIMARY KEY,\n \"Value\" TEXT NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"UpdatedAt\" TEXT NOT NULL,\n \"IsDeleted\" INTEGER NOT NULL DEFAULT 0\n);\n\n-- Tables with foreign keys\nCREATE TABLE \"Credentials\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_Credentials\" PRIMARY KEY,\n \"AliasId\" TEXT NOT NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"Notes\" TEXT NULL,\n \"ServiceId\" TEXT NOT NULL,\n \"UpdatedAt\" TEXT NOT NULL,\n \"Username\" TEXT NULL,\n \"IsDeleted\" INTEGER NOT NULL DEFAULT 0,\n CONSTRAINT \"FK_Credentials_Aliases_AliasId\" FOREIGN KEY (\"AliasId\") REFERENCES \"Aliases\" (\"Id\") ON DELETE CASCADE,\n CONSTRAINT \"FK_Credentials_Services_ServiceId\" FOREIGN KEY (\"ServiceId\") REFERENCES \"Services\" (\"Id\") ON DELETE CASCADE\n);\n\nCREATE TABLE \"Attachments\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_Attachments\" PRIMARY KEY,\n \"Blob\" BLOB NOT NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"CredentialId\" TEXT NOT NULL,\n \"Filename\" TEXT NOT NULL,\n \"IsDeleted\" INTEGER NOT NULL DEFAULT 0,\n \"UpdatedAt\" TEXT NOT NULL,\n CONSTRAINT \"FK_Attachments_Credentials_CredentialId\" FOREIGN KEY (\"CredentialId\") REFERENCES \"Credentials\" (\"Id\") ON DELETE CASCADE\n);\n\nCREATE TABLE \"Passwords\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_Passwords\" PRIMARY KEY,\n \"Value\" TEXT NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"UpdatedAt\" TEXT NOT NULL,\n \"CredentialId\" TEXT NOT NULL,\n \"IsDeleted\" INTEGER NOT NULL DEFAULT 0,\n CONSTRAINT \"FK_Passwords_Credentials_CredentialId\" FOREIGN KEY (\"CredentialId\") REFERENCES \"Credentials\" (\"Id\") ON DELETE CASCADE\n);\n\nCREATE TABLE \"TotpCodes\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_TotpCodes\" PRIMARY KEY,\n \"Name\" TEXT NOT NULL,\n \"SecretKey\" TEXT NOT NULL,\n \"CredentialId\" TEXT NOT NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"UpdatedAt\" TEXT NOT NULL,\n \"IsDeleted\" INTEGER NOT NULL DEFAULT 0,\n CONSTRAINT \"FK_TotpCodes_Credentials_CredentialId\" FOREIGN KEY (\"CredentialId\") REFERENCES \"Credentials\" (\"Id\") ON DELETE CASCADE\n);\n\n\n-- Restore data from temp tables\nINSERT INTO \"__EFMigrationsHistory\" SELECT * FROM \"__EFMigrationsHistory_temp\";\nINSERT INTO \"Aliases\" SELECT * FROM \"Aliases_temp\";\nINSERT INTO \"Services\" SELECT * FROM \"Services_temp\";\nINSERT INTO \"EncryptionKeys\" SELECT * FROM \"EncryptionKeys_temp\";\nINSERT INTO \"Settings\" SELECT * FROM \"Settings_temp\";\nINSERT INTO \"Credentials\" SELECT * FROM \"Credentials_temp\";\nINSERT INTO \"Attachments\" SELECT * FROM \"Attachments_temp\";\nINSERT INTO \"Passwords\" SELECT * FROM \"Passwords_temp\";\nINSERT INTO \"TotpCodes\" SELECT * FROM \"TotpCodes_temp\";\n\n-- =====================================================================================\n-- Date Format Normalization Migration\n-- =====================================================================================\n-- This migration normalizes ALL date fields to the standard format: 'yyyy-MM-dd HH:mm:ss.fff'\n-- Previously the different clients used different date formats which complicate date parsing.\n-- From version 0.24.0 onwards, all new dates are stored in this standard format.\n\n-- Update Aliases table (CreatedAt, UpdatedAt, BirthDate)\nUPDATE \"Aliases\" SET \"CreatedAt\" =\n CASE\n -- Already in correct format (yyyy-MM-dd HH:mm:ss.fff) - no change\n WHEN \"CreatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9] [0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9][0-9][0-9]'\n THEN \"CreatedAt\"\n\n -- ISO 8601 with milliseconds (yyyy-MM-ddTHH:mm:ss.fffZ) -> Replace T with space, remove Z and everything after .fff\n WHEN \"CreatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]T[0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9]*'\n THEN substr(\"CreatedAt\", 1, 10) || ' ' || substr(\"CreatedAt\", 12, 12)\n\n -- Without milliseconds (yyyy-MM-dd HH:mm:ss or yyyy-MM-ddTHH:mm:ssZ) -> Add .000\n WHEN \"CreatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9][T ][0-9][0-9]:[0-9][0-9]:[0-9][0-9]*'\n THEN substr(\"CreatedAt\", 1, 10) || ' ' || substr(replace(\"CreatedAt\", 'T', ' '), 12, 8) || '.000'\n\n -- Fallback: if none match, keep as-is (edge case)\n ELSE \"CreatedAt\"\n END;\n\nUPDATE \"Aliases\" SET \"UpdatedAt\" =\n CASE\n WHEN \"UpdatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9] [0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9][0-9][0-9]'\n THEN \"UpdatedAt\"\n WHEN \"UpdatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]T[0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9]*'\n THEN substr(\"UpdatedAt\", 1, 10) || ' ' || substr(\"UpdatedAt\", 12, 12)\n WHEN \"UpdatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9][T ][0-9][0-9]:[0-9][0-9]:[0-9][0-9]*'\n THEN substr(\"UpdatedAt\", 1, 10) || ' ' || substr(replace(\"UpdatedAt\", 'T', ' '), 12, 8) || '.000'\n ELSE \"UpdatedAt\"\n END;\n\n-- BirthDate: Always set time to 00:00:00 (no milliseconds for birth dates)\nUPDATE \"Aliases\" SET \"BirthDate\" =\n CASE\n -- If empty or already '0001-01-01 00:00:00', keep as-is\n WHEN \"BirthDate\" = '' OR \"BirthDate\" = '0001-01-01 00:00:00'\n THEN \"BirthDate\"\n\n -- If already in correct format (yyyy-MM-dd 00:00:00), keep as-is\n WHEN \"BirthDate\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9] 00:00:00'\n THEN \"BirthDate\"\n\n -- Extract date part and set time to 00:00:00\n WHEN \"BirthDate\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]*'\n THEN substr(\"BirthDate\", 1, 10) || ' 00:00:00'\n\n -- Fallback\n ELSE \"BirthDate\"\n END;\n\n-- Update Services table (CreatedAt, UpdatedAt)\nUPDATE \"Services\" SET \"CreatedAt\" =\n CASE\n WHEN \"CreatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9] [0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9][0-9][0-9]'\n THEN \"CreatedAt\"\n WHEN \"CreatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]T[0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9]*'\n THEN substr(\"CreatedAt\", 1, 10) || ' ' || substr(\"CreatedAt\", 12, 12)\n WHEN \"CreatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9][T ][0-9][0-9]:[0-9][0-9]:[0-9][0-9]*'\n THEN substr(\"CreatedAt\", 1, 10) || ' ' || substr(replace(\"CreatedAt\", 'T', ' '), 12, 8) || '.000'\n ELSE \"CreatedAt\"\n END;\n\nUPDATE \"Services\" SET \"UpdatedAt\" =\n CASE\n WHEN \"UpdatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9] [0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9][0-9][0-9]'\n THEN \"UpdatedAt\"\n WHEN \"UpdatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]T[0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9]*'\n THEN substr(\"UpdatedAt\", 1, 10) || ' ' || substr(\"UpdatedAt\", 12, 12)\n WHEN \"UpdatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9][T ][0-9][0-9]:[0-9][0-9]:[0-9][0-9]*'\n THEN substr(\"UpdatedAt\", 1, 10) || ' ' || substr(replace(\"UpdatedAt\", 'T', ' '), 12, 8) || '.000'\n ELSE \"UpdatedAt\"\n END;\n\n-- Update EncryptionKeys table (CreatedAt, UpdatedAt)\nUPDATE \"EncryptionKeys\" SET \"CreatedAt\" =\n CASE\n WHEN \"CreatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9] [0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9][0-9][0-9]'\n THEN \"CreatedAt\"\n WHEN \"CreatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]T[0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9]*'\n THEN substr(\"CreatedAt\", 1, 10) || ' ' || substr(\"CreatedAt\", 12, 12)\n WHEN \"CreatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9][T ][0-9][0-9]:[0-9][0-9]:[0-9][0-9]*'\n THEN substr(\"CreatedAt\", 1, 10) || ' ' || substr(replace(\"CreatedAt\", 'T', ' '), 12, 8) || '.000'\n ELSE \"CreatedAt\"\n END;\n\nUPDATE \"EncryptionKeys\" SET \"UpdatedAt\" =\n CASE\n WHEN \"UpdatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9] [0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9][0-9][0-9]'\n THEN \"UpdatedAt\"\n WHEN \"UpdatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]T[0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9]*'\n THEN substr(\"UpdatedAt\", 1, 10) || ' ' || substr(\"UpdatedAt\", 12, 12)\n WHEN \"UpdatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9][T ][0-9][0-9]:[0-9][0-9]:[0-9][0-9]*'\n THEN substr(\"UpdatedAt\", 1, 10) || ' ' || substr(replace(\"UpdatedAt\", 'T', ' '), 12, 8) || '.000'\n ELSE \"UpdatedAt\"\n END;\n\n-- Update Settings table (CreatedAt, UpdatedAt)\nUPDATE \"Settings\" SET \"CreatedAt\" =\n CASE\n WHEN \"CreatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9] [0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9][0-9][0-9]'\n THEN \"CreatedAt\"\n WHEN \"CreatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]T[0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9]*'\n THEN substr(\"CreatedAt\", 1, 10) || ' ' || substr(\"CreatedAt\", 12, 12)\n WHEN \"CreatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9][T ][0-9][0-9]:[0-9][0-9]:[0-9][0-9]*'\n THEN substr(\"CreatedAt\", 1, 10) || ' ' || substr(replace(\"CreatedAt\", 'T', ' '), 12, 8) || '.000'\n ELSE \"CreatedAt\"\n END;\n\nUPDATE \"Settings\" SET \"UpdatedAt\" =\n CASE\n WHEN \"UpdatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9] [0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9][0-9][0-9]'\n THEN \"UpdatedAt\"\n WHEN \"UpdatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]T[0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9]*'\n THEN substr(\"UpdatedAt\", 1, 10) || ' ' || substr(\"UpdatedAt\", 12, 12)\n WHEN \"UpdatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9][T ][0-9][0-9]:[0-9][0-9]:[0-9][0-9]*'\n THEN substr(\"UpdatedAt\", 1, 10) || ' ' || substr(replace(\"UpdatedAt\", 'T', ' '), 12, 8) || '.000'\n ELSE \"UpdatedAt\"\n END;\n\n-- Update Credentials table (CreatedAt, UpdatedAt)\nUPDATE \"Credentials\" SET \"CreatedAt\" =\n CASE\n WHEN \"CreatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9] [0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9][0-9][0-9]'\n THEN \"CreatedAt\"\n WHEN \"CreatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]T[0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9]*'\n THEN substr(\"CreatedAt\", 1, 10) || ' ' || substr(\"CreatedAt\", 12, 12)\n WHEN \"CreatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9][T ][0-9][0-9]:[0-9][0-9]:[0-9][0-9]*'\n THEN substr(\"CreatedAt\", 1, 10) || ' ' || substr(replace(\"CreatedAt\", 'T', ' '), 12, 8) || '.000'\n ELSE \"CreatedAt\"\n END;\n\nUPDATE \"Credentials\" SET \"UpdatedAt\" =\n CASE\n WHEN \"UpdatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9] [0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9][0-9][0-9]'\n THEN \"UpdatedAt\"\n WHEN \"UpdatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]T[0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9]*'\n THEN substr(\"UpdatedAt\", 1, 10) || ' ' || substr(\"UpdatedAt\", 12, 12)\n WHEN \"UpdatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9][T ][0-9][0-9]:[0-9][0-9]:[0-9][0-9]*'\n THEN substr(\"UpdatedAt\", 1, 10) || ' ' || substr(replace(\"UpdatedAt\", 'T', ' '), 12, 8) || '.000'\n ELSE \"UpdatedAt\"\n END;\n\n-- Update Attachments table (CreatedAt, UpdatedAt)\nUPDATE \"Attachments\" SET \"CreatedAt\" =\n CASE\n WHEN \"CreatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9] [0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9][0-9][0-9]'\n THEN \"CreatedAt\"\n WHEN \"CreatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]T[0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9]*'\n THEN substr(\"CreatedAt\", 1, 10) || ' ' || substr(\"CreatedAt\", 12, 12)\n WHEN \"CreatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9][T ][0-9][0-9]:[0-9][0-9]:[0-9][0-9]*'\n THEN substr(\"CreatedAt\", 1, 10) || ' ' || substr(replace(\"CreatedAt\", 'T', ' '), 12, 8) || '.000'\n ELSE \"CreatedAt\"\n END;\n\nUPDATE \"Attachments\" SET \"UpdatedAt\" =\n CASE\n WHEN \"UpdatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9] [0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9][0-9][0-9]'\n THEN \"UpdatedAt\"\n WHEN \"UpdatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]T[0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9]*'\n THEN substr(\"UpdatedAt\", 1, 10) || ' ' || substr(\"UpdatedAt\", 12, 12)\n WHEN \"UpdatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9][T ][0-9][0-9]:[0-9][0-9]:[0-9][0-9]*'\n THEN substr(\"UpdatedAt\", 1, 10) || ' ' || substr(replace(\"UpdatedAt\", 'T', ' '), 12, 8) || '.000'\n ELSE \"UpdatedAt\"\n END;\n\n-- Update Passwords table (CreatedAt, UpdatedAt)\nUPDATE \"Passwords\" SET \"CreatedAt\" =\n CASE\n WHEN \"CreatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9] [0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9][0-9][0-9]'\n THEN \"CreatedAt\"\n WHEN \"CreatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]T[0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9]*'\n THEN substr(\"CreatedAt\", 1, 10) || ' ' || substr(\"CreatedAt\", 12, 12)\n WHEN \"CreatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9][T ][0-9][0-9]:[0-9][0-9]:[0-9][0-9]*'\n THEN substr(\"CreatedAt\", 1, 10) || ' ' || substr(replace(\"CreatedAt\", 'T', ' '), 12, 8) || '.000'\n ELSE \"CreatedAt\"\n END;\n\nUPDATE \"Passwords\" SET \"UpdatedAt\" =\n CASE\n WHEN \"UpdatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9] [0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9][0-9][0-9]'\n THEN \"UpdatedAt\"\n WHEN \"UpdatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]T[0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9]*'\n THEN substr(\"UpdatedAt\", 1, 10) || ' ' || substr(\"UpdatedAt\", 12, 12)\n WHEN \"UpdatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9][T ][0-9][0-9]:[0-9][0-9]:[0-9][0-9]*'\n THEN substr(\"UpdatedAt\", 1, 10) || ' ' || substr(replace(\"UpdatedAt\", 'T', ' '), 12, 8) || '.000'\n ELSE \"UpdatedAt\"\n END;\n\n-- Update TotpCodes table (CreatedAt, UpdatedAt)\nUPDATE \"TotpCodes\" SET \"CreatedAt\" =\n CASE\n WHEN \"CreatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9] [0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9][0-9][0-9]'\n THEN \"CreatedAt\"\n WHEN \"CreatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]T[0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9]*'\n THEN substr(\"CreatedAt\", 1, 10) || ' ' || substr(\"CreatedAt\", 12, 12)\n WHEN \"CreatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9][T ][0-9][0-9]:[0-9][0-9]:[0-9][0-9]*'\n THEN substr(\"CreatedAt\", 1, 10) || ' ' || substr(replace(\"CreatedAt\", 'T', ' '), 12, 8) || '.000'\n ELSE \"CreatedAt\"\n END;\n\nUPDATE \"TotpCodes\" SET \"UpdatedAt\" =\n CASE\n WHEN \"UpdatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9] [0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9][0-9][0-9]'\n THEN \"UpdatedAt\"\n WHEN \"UpdatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]T[0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9]*'\n THEN substr(\"UpdatedAt\", 1, 10) || ' ' || substr(\"UpdatedAt\", 12, 12)\n WHEN \"UpdatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9][T ][0-9][0-9]:[0-9][0-9]:[0-9][0-9]*'\n THEN substr(\"UpdatedAt\", 1, 10) || ' ' || substr(replace(\"UpdatedAt\", 'T', ' '), 12, 8) || '.000'\n ELSE \"UpdatedAt\"\n END;\n\n-- =====================================================================================\n-- End of Date Format Normalization Migration\n-- =====================================================================================\n\n-- Recreate indexes\nCREATE INDEX \"IX_Credentials_AliasId\" ON \"Credentials\" (\"AliasId\");\nCREATE INDEX \"IX_Credentials_ServiceId\" ON \"Credentials\" (\"ServiceId\");\nCREATE INDEX \"IX_Attachments_CredentialId\" ON \"Attachments\" (\"CredentialId\");\nCREATE INDEX \"IX_Passwords_CredentialId\" ON \"Passwords\" (\"CredentialId\");\nCREATE INDEX \"IX_TotpCodes_CredentialId\" ON \"TotpCodes\" (\"CredentialId\");\n\n-- Clean up temp tables\nDROP TABLE \"__EFMigrationsHistory_temp\";\nDROP TABLE \"Aliases_temp\";\nDROP TABLE \"Services_temp\";\nDROP TABLE \"EncryptionKeys_temp\";\nDROP TABLE \"Settings_temp\";\nDROP TABLE \"Credentials_temp\";\nDROP TABLE \"Attachments_temp\";\nDROP TABLE \"Passwords_temp\";\nDROP TABLE \"TotpCodes_temp\";\n\nPRAGMA foreign_keys = ON;\n\n\nCREATE TABLE \"Passkeys\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_Passkeys\" PRIMARY KEY,\n \"RpId\" TEXT COLLATE NOCASE NOT NULL,\n \"UserHandle\" BLOB NOT NULL,\n \"PublicKey\" TEXT NOT NULL,\n \"PrivateKey\" TEXT NOT NULL,\n \"PrfKey\" BLOB NULL,\n \"DisplayName\" TEXT NOT NULL,\n \"AdditionalData\" BLOB NULL,\n \"CredentialId\" TEXT NOT NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"UpdatedAt\" TEXT NOT NULL,\n \"IsDeleted\" INTEGER NOT NULL,\n CONSTRAINT \"FK_Passkeys_Credentials_CredentialId\" FOREIGN KEY (\"CredentialId\") REFERENCES \"Credentials\" (\"Id\") ON DELETE CASCADE\n);\n\nCREATE INDEX \"IX_Passkeys_CredentialId\" ON \"Passkeys\" (\"CredentialId\");\n\nCREATE INDEX \"IX_Passkeys_RpId\" ON \"Passkeys\" (\"RpId\");\n\nINSERT INTO \"__EFMigrationsHistory\" (\"MigrationId\", \"ProductVersion\")\nVALUES ('20251014122838_1.6.0-AddPasskeys', '9.0.4');\n\nALTER TABLE \"TotpCodes\" RENAME COLUMN \"CredentialId\" TO \"ItemId\";\n\nDROP INDEX IF EXISTS \"IX_TotpCodes_CredentialId\";\n\nCREATE INDEX IF NOT EXISTS \"IX_TotpCodes_ItemId\" ON \"TotpCodes\" (\"ItemId\");\n\nALTER TABLE \"Passkeys\" RENAME COLUMN \"CredentialId\" TO \"ItemId\";\n\nDROP INDEX IF EXISTS \"IX_Passkeys_CredentialId\";\n\nCREATE INDEX IF NOT EXISTS \"IX_Passkeys_ItemId\" ON \"Passkeys\" (\"ItemId\");\n\nALTER TABLE \"Attachments\" RENAME COLUMN \"CredentialId\" TO \"ItemId\";\n\nDROP INDEX IF EXISTS \"IX_Attachments_CredentialId\";\n\nCREATE INDEX IF NOT EXISTS \"IX_Attachments_ItemId\" ON \"Attachments\" (\"ItemId\");\n\nCREATE TABLE \"FieldDefinitions\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_FieldDefinitions\" PRIMARY KEY,\n \"FieldType\" TEXT NOT NULL,\n \"Label\" TEXT NOT NULL,\n \"IsMultiValue\" INTEGER NOT NULL,\n \"IsHidden\" INTEGER NOT NULL,\n \"EnableHistory\" INTEGER NOT NULL,\n \"Weight\" INTEGER NOT NULL,\n \"ApplicableToTypes\" TEXT NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"UpdatedAt\" TEXT NOT NULL,\n \"IsDeleted\" INTEGER NOT NULL\n);\n\nCREATE TABLE \"Folders\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_Folders\" PRIMARY KEY,\n \"Name\" TEXT NOT NULL,\n \"ParentFolderId\" TEXT NULL,\n \"Weight\" INTEGER NOT NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"UpdatedAt\" TEXT NOT NULL,\n \"IsDeleted\" INTEGER NOT NULL,\n CONSTRAINT \"FK_Folders_Folders_ParentFolderId\" FOREIGN KEY (\"ParentFolderId\") REFERENCES \"Folders\" (\"Id\") ON DELETE CASCADE\n);\n\nCREATE TABLE \"Logos\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_Logos\" PRIMARY KEY,\n \"Source\" TEXT NOT NULL,\n \"FileData\" BLOB NULL,\n \"MimeType\" TEXT NULL,\n \"FetchedAt\" TEXT NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"UpdatedAt\" TEXT NOT NULL,\n \"IsDeleted\" INTEGER NOT NULL\n);\n\nCREATE TABLE \"Tags\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_Tags\" PRIMARY KEY,\n \"Name\" TEXT NOT NULL,\n \"Color\" TEXT NULL,\n \"DisplayOrder\" INTEGER NOT NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"UpdatedAt\" TEXT NOT NULL,\n \"IsDeleted\" INTEGER NOT NULL\n);\n\nCREATE TABLE \"Items\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_Items\" PRIMARY KEY,\n \"Name\" TEXT NULL,\n \"ItemType\" TEXT NOT NULL,\n \"LogoId\" TEXT NULL,\n \"DeletedAt\" TEXT NULL,\n \"FolderId\" TEXT NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"UpdatedAt\" TEXT NOT NULL,\n \"IsDeleted\" INTEGER NOT NULL,\n CONSTRAINT \"FK_Items_Folders_FolderId\" FOREIGN KEY (\"FolderId\") REFERENCES \"Folders\" (\"Id\") ON DELETE SET NULL,\n CONSTRAINT \"FK_Items_Logos_LogoId\" FOREIGN KEY (\"LogoId\") REFERENCES \"Logos\" (\"Id\") ON DELETE SET NULL\n);\n\nCREATE TABLE \"FieldHistories\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_FieldHistories\" PRIMARY KEY,\n \"ItemId\" TEXT NOT NULL,\n \"FieldDefinitionId\" TEXT NULL,\n \"FieldKey\" TEXT NULL,\n \"ValueSnapshot\" TEXT NOT NULL,\n \"ChangedAt\" TEXT NOT NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"UpdatedAt\" TEXT NOT NULL,\n \"IsDeleted\" INTEGER NOT NULL,\n CONSTRAINT \"FK_FieldHistories_FieldDefinitions_FieldDefinitionId\" FOREIGN KEY (\"FieldDefinitionId\") REFERENCES \"FieldDefinitions\" (\"Id\") ON DELETE CASCADE,\n CONSTRAINT \"FK_FieldHistories_Items_ItemId\" FOREIGN KEY (\"ItemId\") REFERENCES \"Items\" (\"Id\") ON DELETE CASCADE\n);\n\nCREATE TABLE \"FieldValues\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_FieldValues\" PRIMARY KEY,\n \"ItemId\" TEXT NOT NULL,\n \"FieldDefinitionId\" TEXT NULL,\n \"FieldKey\" TEXT NULL,\n \"Value\" TEXT NULL,\n \"Weight\" INTEGER NOT NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"UpdatedAt\" TEXT NOT NULL,\n \"IsDeleted\" INTEGER NOT NULL,\n CONSTRAINT \"FK_FieldValues_FieldDefinitions_FieldDefinitionId\" FOREIGN KEY (\"FieldDefinitionId\") REFERENCES \"FieldDefinitions\" (\"Id\") ON DELETE CASCADE,\n CONSTRAINT \"FK_FieldValues_Items_ItemId\" FOREIGN KEY (\"ItemId\") REFERENCES \"Items\" (\"Id\") ON DELETE CASCADE\n);\n\nCREATE TABLE \"ItemTags\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_ItemTags\" PRIMARY KEY,\n \"ItemId\" TEXT NOT NULL,\n \"TagId\" TEXT NOT NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"UpdatedAt\" TEXT NOT NULL,\n \"IsDeleted\" INTEGER NOT NULL,\n CONSTRAINT \"FK_ItemTags_Items_ItemId\" FOREIGN KEY (\"ItemId\") REFERENCES \"Items\" (\"Id\") ON DELETE CASCADE,\n CONSTRAINT \"FK_ItemTags_Tags_TagId\" FOREIGN KEY (\"TagId\") REFERENCES \"Tags\" (\"Id\") ON DELETE CASCADE\n);\n\nCREATE INDEX \"IX_FieldHistories_FieldDefinitionId\" ON \"FieldHistories\" (\"FieldDefinitionId\");\n\nCREATE INDEX \"IX_FieldHistories_ItemId\" ON \"FieldHistories\" (\"ItemId\");\n\nCREATE INDEX \"IX_FieldValues_FieldDefinitionId\" ON \"FieldValues\" (\"FieldDefinitionId\");\n\nCREATE INDEX \"IX_FieldValues_FieldKey\" ON \"FieldValues\" (\"FieldKey\");\n\nCREATE INDEX \"IX_FieldValues_ItemId\" ON \"FieldValues\" (\"ItemId\");\n\nCREATE INDEX \"IX_FieldValues_ItemId_FieldDefinitionId_Weight\" ON \"FieldValues\" (\"ItemId\", \"FieldDefinitionId\", \"Weight\");\n\nCREATE INDEX \"IX_FieldValues_ItemId_FieldKey\" ON \"FieldValues\" (\"ItemId\", \"FieldKey\");\n\nCREATE INDEX \"IX_Folders_ParentFolderId\" ON \"Folders\" (\"ParentFolderId\");\n\nCREATE INDEX \"IX_Items_FolderId\" ON \"Items\" (\"FolderId\");\n\nCREATE INDEX \"IX_Items_LogoId\" ON \"Items\" (\"LogoId\");\n\nCREATE INDEX \"IX_ItemTags_ItemId\" ON \"ItemTags\" (\"ItemId\");\n\nCREATE UNIQUE INDEX \"IX_ItemTags_ItemId_TagId\" ON \"ItemTags\" (\"ItemId\", \"TagId\");\n\nCREATE INDEX \"IX_ItemTags_TagId\" ON \"ItemTags\" (\"TagId\");\n\nCREATE UNIQUE INDEX \"IX_Logos_Source\" ON \"Logos\" (\"Source\");\n\nCREATE INDEX \"IX_Tags_Name\" ON \"Tags\" (\"Name\");\n\n\n INSERT INTO Items (Id, Name, ItemType, LogoId, FolderId, CreatedAt, UpdatedAt, IsDeleted)\n SELECT\n c.Id,\n s.Name AS Name,\n CASE\n WHEN a.Id IS NOT NULL AND (\n (a.FirstName IS NOT NULL AND a.FirstName != '') OR\n (a.LastName IS NOT NULL AND a.LastName != '') OR\n (a.Gender IS NOT NULL AND a.Gender != '') OR\n (a.BirthDate IS NOT NULL AND a.BirthDate != '' AND a.BirthDate NOT LIKE '0001-%')\n ) THEN 'Alias'\n ELSE 'Login'\n END AS ItemType,\n NULL AS LogoId,\n NULL AS FolderId,\n c.CreatedAt,\n c.UpdatedAt,\n c.IsDeleted\n FROM Credentials c\n LEFT JOIN Services s ON s.Id = c.ServiceId\n LEFT JOIN Aliases a ON a.Id = c.AliasId;\n \n\n\n INSERT INTO Logos (Id, Source, FileData, MimeType, FetchedAt, CreatedAt, UpdatedAt, IsDeleted)\n SELECT\n UPPER(SUBSTR(hex(randomblob(4)), 1, 8) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(6)), 1, 12)) AS Id,\n -- Extract and normalize hostname: remove protocol, path, lowercase, and www. prefix\n REPLACE(\n LOWER(\n SUBSTR(\n CASE\n WHEN s.Url LIKE 'https://%' THEN SUBSTR(s.Url, 9)\n WHEN s.Url LIKE 'http://%' THEN SUBSTR(s.Url, 8)\n ELSE s.Url\n END,\n 1,\n CASE\n WHEN INSTR(\n CASE\n WHEN s.Url LIKE 'https://%' THEN SUBSTR(s.Url, 9)\n WHEN s.Url LIKE 'http://%' THEN SUBSTR(s.Url, 8)\n ELSE s.Url\n END, '/') > 0\n THEN INSTR(\n CASE\n WHEN s.Url LIKE 'https://%' THEN SUBSTR(s.Url, 9)\n WHEN s.Url LIKE 'http://%' THEN SUBSTR(s.Url, 8)\n ELSE s.Url\n END, '/') - 1\n ELSE LENGTH(\n CASE\n WHEN s.Url LIKE 'https://%' THEN SUBSTR(s.Url, 9)\n WHEN s.Url LIKE 'http://%' THEN SUBSTR(s.Url, 8)\n ELSE s.Url\n END)\n END\n )\n ),\n 'www.', ''\n ) AS Source,\n s.Logo AS FileData,\n 'image/png' AS MimeType,\n NULL AS FetchedAt,\n MIN(s.CreatedAt) AS CreatedAt,\n MAX(s.UpdatedAt) AS UpdatedAt,\n 0 AS IsDeleted\n FROM Services s\n WHERE s.Logo IS NOT NULL AND s.Url IS NOT NULL AND s.Url != ''\n GROUP BY REPLACE(\n LOWER(\n SUBSTR(\n CASE\n WHEN s.Url LIKE 'https://%' THEN SUBSTR(s.Url, 9)\n WHEN s.Url LIKE 'http://%' THEN SUBSTR(s.Url, 8)\n ELSE s.Url\n END,\n 1,\n CASE\n WHEN INSTR(\n CASE\n WHEN s.Url LIKE 'https://%' THEN SUBSTR(s.Url, 9)\n WHEN s.Url LIKE 'http://%' THEN SUBSTR(s.Url, 8)\n ELSE s.Url\n END, '/') > 0\n THEN INSTR(\n CASE\n WHEN s.Url LIKE 'https://%' THEN SUBSTR(s.Url, 9)\n WHEN s.Url LIKE 'http://%' THEN SUBSTR(s.Url, 8)\n ELSE s.Url\n END, '/') - 1\n ELSE LENGTH(\n CASE\n WHEN s.Url LIKE 'https://%' THEN SUBSTR(s.Url, 9)\n WHEN s.Url LIKE 'http://%' THEN SUBSTR(s.Url, 8)\n ELSE s.Url\n END)\n END\n )\n ),\n 'www.', ''\n );\n \n\n\n UPDATE Items\n SET LogoId = (\n SELECT l.Id FROM Logos l\n INNER JOIN Services s ON REPLACE(\n LOWER(\n SUBSTR(\n CASE\n WHEN s.Url LIKE 'https://%' THEN SUBSTR(s.Url, 9)\n WHEN s.Url LIKE 'http://%' THEN SUBSTR(s.Url, 8)\n ELSE s.Url\n END,\n 1,\n CASE\n WHEN INSTR(\n CASE\n WHEN s.Url LIKE 'https://%' THEN SUBSTR(s.Url, 9)\n WHEN s.Url LIKE 'http://%' THEN SUBSTR(s.Url, 8)\n ELSE s.Url\n END, '/') > 0\n THEN INSTR(\n CASE\n WHEN s.Url LIKE 'https://%' THEN SUBSTR(s.Url, 9)\n WHEN s.Url LIKE 'http://%' THEN SUBSTR(s.Url, 8)\n ELSE s.Url\n END, '/') - 1\n ELSE LENGTH(\n CASE\n WHEN s.Url LIKE 'https://%' THEN SUBSTR(s.Url, 9)\n WHEN s.Url LIKE 'http://%' THEN SUBSTR(s.Url, 8)\n ELSE s.Url\n END)\n END\n )\n ),\n 'www.', ''\n ) = l.Source\n INNER JOIN Credentials c ON c.ServiceId = s.Id\n WHERE c.Id = Items.Id\n LIMIT 1\n )\n WHERE EXISTS (\n SELECT 1 FROM Credentials c\n INNER JOIN Services s ON s.Id = c.ServiceId\n WHERE c.Id = Items.Id AND s.Logo IS NOT NULL\n );\n \n\n\n INSERT INTO FieldValues (Id, ItemId, FieldDefinitionId, FieldKey, Value, Weight, CreatedAt, UpdatedAt, IsDeleted)\n SELECT\n UPPER(SUBSTR(hex(randomblob(4)), 1, 8) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(6)), 1, 12)) AS Id,\n c.Id AS ItemId,\n NULL AS FieldDefinitionId,\n 'login.url' AS FieldKey,\n s.Url AS Value,\n 0 AS Weight,\n s.UpdatedAt AS CreatedAt,\n s.UpdatedAt AS UpdatedAt,\n 0 AS IsDeleted\n FROM Credentials c\n INNER JOIN Services s ON s.Id = c.ServiceId\n WHERE s.Url IS NOT NULL AND s.Url != '';\n \n\n\n INSERT INTO FieldValues (Id, ItemId, FieldDefinitionId, FieldKey, Value, Weight, CreatedAt, UpdatedAt, IsDeleted)\n SELECT\n UPPER(SUBSTR(hex(randomblob(4)), 1, 8) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(6)), 1, 12)) AS Id,\n c.Id AS ItemId,\n NULL AS FieldDefinitionId,\n 'login.username' AS FieldKey,\n c.Username AS Value,\n 0 AS Weight,\n c.UpdatedAt AS CreatedAt,\n c.UpdatedAt AS UpdatedAt,\n 0 AS IsDeleted\n FROM Credentials c\n WHERE c.Username IS NOT NULL AND c.Username != '';\n \n\n\n INSERT INTO FieldValues (Id, ItemId, FieldDefinitionId, FieldKey, Value, Weight, CreatedAt, UpdatedAt, IsDeleted)\n SELECT\n UPPER(SUBSTR(hex(randomblob(4)), 1, 8) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(6)), 1, 12)) AS Id,\n c.Id AS ItemId,\n NULL AS FieldDefinitionId,\n 'login.notes' AS FieldKey,\n c.Notes AS Value,\n 0 AS Weight,\n c.UpdatedAt AS CreatedAt,\n c.UpdatedAt AS UpdatedAt,\n 0 AS IsDeleted\n FROM Credentials c\n WHERE c.Notes IS NOT NULL AND c.Notes != '';\n \n\n\n INSERT INTO FieldValues (Id, ItemId, FieldDefinitionId, FieldKey, Value, Weight, CreatedAt, UpdatedAt, IsDeleted)\n SELECT\n UPPER(SUBSTR(hex(randomblob(4)), 1, 8) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(6)), 1, 12)) AS Id,\n p.CredentialId AS ItemId,\n NULL AS FieldDefinitionId,\n 'login.password' AS FieldKey,\n p.Value AS Value,\n 0 AS Weight,\n p.UpdatedAt AS CreatedAt,\n p.UpdatedAt AS UpdatedAt,\n 0 AS IsDeleted\n FROM Passwords p\n INNER JOIN (\n SELECT CredentialId, MAX(UpdatedAt) AS MaxUpdated, MAX(Id) AS MaxId\n FROM Passwords\n WHERE IsDeleted = 0\n GROUP BY CredentialId\n ) pm ON p.CredentialId = pm.CredentialId AND p.UpdatedAt = pm.MaxUpdated AND p.Id = pm.MaxId\n WHERE p.IsDeleted = 0;\n \n\n\n INSERT INTO FieldValues (Id, ItemId, FieldDefinitionId, FieldKey, Value, Weight, CreatedAt, UpdatedAt, IsDeleted)\n SELECT\n UPPER(SUBSTR(hex(randomblob(4)), 1, 8) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(6)), 1, 12)) AS Id,\n c.Id AS ItemId,\n NULL AS FieldDefinitionId,\n 'login.email' AS FieldKey,\n a.Email AS Value,\n 0 AS Weight,\n a.UpdatedAt AS CreatedAt,\n a.UpdatedAt AS UpdatedAt,\n 0 AS IsDeleted\n FROM Credentials c\n INNER JOIN Aliases a ON a.Id = c.AliasId\n WHERE a.Email IS NOT NULL AND a.Email != '';\n \n\n\n INSERT INTO FieldValues (Id, ItemId, FieldDefinitionId, FieldKey, Value, Weight, CreatedAt, UpdatedAt, IsDeleted)\n SELECT\n UPPER(SUBSTR(hex(randomblob(4)), 1, 8) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(6)), 1, 12)) AS Id,\n c.Id AS ItemId,\n NULL AS FieldDefinitionId,\n 'alias.first_name' AS FieldKey,\n a.FirstName AS Value,\n 0 AS Weight,\n a.UpdatedAt AS CreatedAt,\n a.UpdatedAt AS UpdatedAt,\n 0 AS IsDeleted\n FROM Credentials c\n INNER JOIN Aliases a ON a.Id = c.AliasId\n WHERE a.FirstName IS NOT NULL AND a.FirstName != '';\n \n\n\n INSERT INTO FieldValues (Id, ItemId, FieldDefinitionId, FieldKey, Value, Weight, CreatedAt, UpdatedAt, IsDeleted)\n SELECT\n UPPER(SUBSTR(hex(randomblob(4)), 1, 8) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(6)), 1, 12)) AS Id,\n c.Id AS ItemId,\n NULL AS FieldDefinitionId,\n 'alias.last_name' AS FieldKey,\n a.LastName AS Value,\n 0 AS Weight,\n a.UpdatedAt AS CreatedAt,\n a.UpdatedAt AS UpdatedAt,\n 0 AS IsDeleted\n FROM Credentials c\n INNER JOIN Aliases a ON a.Id = c.AliasId\n WHERE a.LastName IS NOT NULL AND a.LastName != '';\n \n\n\n INSERT INTO FieldValues (Id, ItemId, FieldDefinitionId, FieldKey, Value, Weight, CreatedAt, UpdatedAt, IsDeleted)\n SELECT\n UPPER(SUBSTR(hex(randomblob(4)), 1, 8) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(6)), 1, 12)) AS Id,\n c.Id AS ItemId,\n NULL AS FieldDefinitionId,\n 'alias.gender' AS FieldKey,\n a.Gender AS Value,\n 0 AS Weight,\n a.UpdatedAt AS CreatedAt,\n a.UpdatedAt AS UpdatedAt,\n 0 AS IsDeleted\n FROM Credentials c\n INNER JOIN Aliases a ON a.Id = c.AliasId\n WHERE a.Gender IS NOT NULL AND a.Gender != '';\n \n\n\n INSERT INTO FieldValues (Id, ItemId, FieldDefinitionId, FieldKey, Value, Weight, CreatedAt, UpdatedAt, IsDeleted)\n SELECT\n UPPER(SUBSTR(hex(randomblob(4)), 1, 8) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(6)), 1, 12)) AS Id,\n c.Id AS ItemId,\n NULL AS FieldDefinitionId,\n 'alias.birthdate' AS FieldKey,\n SUBSTR(a.BirthDate, 1, 10) AS Value,\n 0 AS Weight,\n a.UpdatedAt AS CreatedAt,\n a.UpdatedAt AS UpdatedAt,\n 0 AS IsDeleted\n FROM Credentials c\n INNER JOIN Aliases a ON a.Id = c.AliasId\n WHERE a.BirthDate IS NOT NULL AND a.BirthDate != '' AND a.BirthDate NOT LIKE '0001-%';\n \n\nDROP TABLE \"Passwords\";\n\nDROP TABLE \"Credentials\";\n\nDROP TABLE \"Aliases\";\n\nDROP TABLE \"Services\";\n\nCREATE TABLE \"ef_temp_Attachments\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_Attachments\" PRIMARY KEY,\n \"Blob\" BLOB NOT NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"Filename\" TEXT NOT NULL,\n \"IsDeleted\" INTEGER NOT NULL,\n \"ItemId\" TEXT NOT NULL,\n \"UpdatedAt\" TEXT NOT NULL,\n CONSTRAINT \"FK_Attachments_Items_ItemId\" FOREIGN KEY (\"ItemId\") REFERENCES \"Items\" (\"Id\") ON DELETE CASCADE\n);\n\nINSERT INTO \"ef_temp_Attachments\" (\"Id\", \"Blob\", \"CreatedAt\", \"Filename\", \"IsDeleted\", \"ItemId\", \"UpdatedAt\")\nSELECT \"Id\", \"Blob\", \"CreatedAt\", \"Filename\", \"IsDeleted\", \"ItemId\", \"UpdatedAt\"\nFROM \"Attachments\";\n\nCREATE TABLE \"ef_temp_Passkeys\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_Passkeys\" PRIMARY KEY,\n \"AdditionalData\" BLOB NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"DisplayName\" TEXT NOT NULL,\n \"IsDeleted\" INTEGER NOT NULL,\n \"ItemId\" TEXT NOT NULL,\n \"PrfKey\" BLOB NULL,\n \"PrivateKey\" TEXT NOT NULL,\n \"PublicKey\" TEXT NOT NULL,\n \"RpId\" TEXT COLLATE NOCASE NOT NULL,\n \"UpdatedAt\" TEXT NOT NULL,\n \"UserHandle\" BLOB NOT NULL,\n CONSTRAINT \"FK_Passkeys_Items_ItemId\" FOREIGN KEY (\"ItemId\") REFERENCES \"Items\" (\"Id\") ON DELETE CASCADE\n);\n\nINSERT INTO \"ef_temp_Passkeys\" (\"Id\", \"AdditionalData\", \"CreatedAt\", \"DisplayName\", \"IsDeleted\", \"ItemId\", \"PrfKey\", \"PrivateKey\", \"PublicKey\", \"RpId\", \"UpdatedAt\", \"UserHandle\")\nSELECT \"Id\", \"AdditionalData\", \"CreatedAt\", \"DisplayName\", \"IsDeleted\", \"ItemId\", \"PrfKey\", \"PrivateKey\", \"PublicKey\", \"RpId\", \"UpdatedAt\", \"UserHandle\"\nFROM \"Passkeys\";\n\nCREATE TABLE \"ef_temp_TotpCodes\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_TotpCodes\" PRIMARY KEY,\n \"CreatedAt\" TEXT NOT NULL,\n \"IsDeleted\" INTEGER NOT NULL,\n \"ItemId\" TEXT NOT NULL,\n \"Name\" TEXT NOT NULL,\n \"SecretKey\" TEXT NOT NULL,\n \"UpdatedAt\" TEXT NOT NULL,\n CONSTRAINT \"FK_TotpCodes_Items_ItemId\" FOREIGN KEY (\"ItemId\") REFERENCES \"Items\" (\"Id\") ON DELETE CASCADE\n);\n\nINSERT INTO \"ef_temp_TotpCodes\" (\"Id\", \"CreatedAt\", \"IsDeleted\", \"ItemId\", \"Name\", \"SecretKey\", \"UpdatedAt\")\nSELECT \"Id\", \"CreatedAt\", \"IsDeleted\", \"ItemId\", \"Name\", \"SecretKey\", \"UpdatedAt\"\nFROM \"TotpCodes\";\n\nCOMMIT;\n\nPRAGMA foreign_keys = 0;\n\nBEGIN TRANSACTION;\nDROP TABLE \"Attachments\";\n\nALTER TABLE \"ef_temp_Attachments\" RENAME TO \"Attachments\";\n\nDROP TABLE \"Passkeys\";\n\nALTER TABLE \"ef_temp_Passkeys\" RENAME TO \"Passkeys\";\n\nDROP TABLE \"TotpCodes\";\n\nALTER TABLE \"ef_temp_TotpCodes\" RENAME TO \"TotpCodes\";\n\nCOMMIT;\n\nPRAGMA foreign_keys = 1;\n\nBEGIN TRANSACTION;\nCREATE INDEX \"IX_Attachments_ItemId\" ON \"Attachments\" (\"ItemId\");\n\nCREATE INDEX \"IX_Passkeys_ItemId\" ON \"Passkeys\" (\"ItemId\");\n\nCREATE INDEX \"IX_Passkeys_RpId\" ON \"Passkeys\" (\"RpId\");\n\nCREATE INDEX \"IX_TotpCodes_ItemId\" ON \"TotpCodes\" (\"ItemId\");\n\nCOMMIT;\n\nINSERT INTO \"__EFMigrationsHistory\" (\"MigrationId\", \"ProductVersion\")\nVALUES ('20251213111207_1.7.0-FieldBasedDataModelUpdate', '9.0.4');\n\nBEGIN TRANSACTION;\nINSERT INTO \"__EFMigrationsHistory\" (\"MigrationId\", \"ProductVersion\")\nVALUES ('20260130221620_2.0.0-MajorVersionBump', '9.0.4');\n\nCOMMIT;\n"; /** * Individual migration SQL scripts * Auto-generated from EF Core migrations diff --git a/apps/browser-extension/src/utils/dist/core/vault/index.d.ts b/apps/browser-extension/src/utils/dist/core/vault/index.d.ts index 033a999f0..0ee327dbe 100644 --- a/apps/browser-extension/src/utils/dist/core/vault/index.d.ts +++ b/apps/browser-extension/src/utils/dist/core/vault/index.d.ts @@ -122,7 +122,7 @@ declare const VAULT_VERSIONS: VaultVersion[]; * Complete database schema SQL (latest version) * Auto-generated from EF Core migrations */ -declare const COMPLETE_SCHEMA_SQL = "\n\uFEFFCREATE TABLE IF NOT EXISTS \"__EFMigrationsHistory\" (\n \"MigrationId\" TEXT NOT NULL CONSTRAINT \"PK___EFMigrationsHistory\" PRIMARY KEY,\n \"ProductVersion\" TEXT NOT NULL\n);\n\nBEGIN TRANSACTION;\nCREATE TABLE \"Aliases\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_Aliases\" PRIMARY KEY,\n \"Gender\" VARCHAR NULL,\n \"FirstName\" VARCHAR NULL,\n \"LastName\" VARCHAR NULL,\n \"NickName\" VARCHAR NULL,\n \"BirthDate\" TEXT NOT NULL,\n \"AddressStreet\" VARCHAR NULL,\n \"AddressCity\" VARCHAR NULL,\n \"AddressState\" VARCHAR NULL,\n \"AddressZipCode\" VARCHAR NULL,\n \"AddressCountry\" VARCHAR NULL,\n \"Hobbies\" TEXT NULL,\n \"EmailPrefix\" TEXT NULL,\n \"PhoneMobile\" TEXT NULL,\n \"BankAccountIBAN\" TEXT NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"UpdatedAt\" TEXT NOT NULL\n);\n\nCREATE TABLE \"Services\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_Services\" PRIMARY KEY,\n \"Name\" TEXT NULL,\n \"Url\" TEXT NULL,\n \"Logo\" BLOB NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"UpdatedAt\" TEXT NOT NULL\n);\n\nCREATE TABLE \"Credentials\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_Credentials\" PRIMARY KEY,\n \"AliasId\" TEXT NOT NULL,\n \"Notes\" TEXT NULL,\n \"Username\" TEXT NOT NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"UpdatedAt\" TEXT NOT NULL,\n \"ServiceId\" TEXT NOT NULL,\n CONSTRAINT \"FK_Credentials_Aliases_AliasId\" FOREIGN KEY (\"AliasId\") REFERENCES \"Aliases\" (\"Id\") ON DELETE CASCADE,\n CONSTRAINT \"FK_Credentials_Services_ServiceId\" FOREIGN KEY (\"ServiceId\") REFERENCES \"Services\" (\"Id\") ON DELETE CASCADE\n);\n\nCREATE TABLE \"Attachment\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_Attachment\" PRIMARY KEY,\n \"Filename\" TEXT NOT NULL,\n \"Blob\" BLOB NOT NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"UpdatedAt\" TEXT NOT NULL,\n \"CredentialId\" TEXT NOT NULL,\n CONSTRAINT \"FK_Attachment_Credentials_CredentialId\" FOREIGN KEY (\"CredentialId\") REFERENCES \"Credentials\" (\"Id\") ON DELETE CASCADE\n);\n\nCREATE TABLE \"Passwords\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_Passwords\" PRIMARY KEY,\n \"Value\" TEXT NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"UpdatedAt\" TEXT NOT NULL,\n \"CredentialId\" TEXT NOT NULL,\n CONSTRAINT \"FK_Passwords_Credentials_CredentialId\" FOREIGN KEY (\"CredentialId\") REFERENCES \"Credentials\" (\"Id\") ON DELETE CASCADE\n);\n\nCREATE INDEX \"IX_Attachment_CredentialId\" ON \"Attachment\" (\"CredentialId\");\n\nCREATE INDEX \"IX_Credentials_AliasId\" ON \"Credentials\" (\"AliasId\");\n\nCREATE INDEX \"IX_Credentials_ServiceId\" ON \"Credentials\" (\"ServiceId\");\n\nCREATE INDEX \"IX_Passwords_CredentialId\" ON \"Passwords\" (\"CredentialId\");\n\nINSERT INTO \"__EFMigrationsHistory\" (\"MigrationId\", \"ProductVersion\")\nVALUES ('20240708094944_1.0.0-InitialMigration', '9.0.4');\n\nINSERT INTO \"__EFMigrationsHistory\" (\"MigrationId\", \"ProductVersion\")\nVALUES ('20240708224522_1.0.1-EmptyTestMigration', '9.0.4');\n\nALTER TABLE \"Aliases\" RENAME COLUMN \"EmailPrefix\" TO \"Email\";\n\nINSERT INTO \"__EFMigrationsHistory\" (\"MigrationId\", \"ProductVersion\")\nVALUES ('20240711204207_1.0.2-ChangeEmailColumn', '9.0.4');\n\nCREATE TABLE \"EncryptionKeys\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_EncryptionKeys\" PRIMARY KEY,\n \"PublicKey\" TEXT NOT NULL,\n \"PrivateKey\" TEXT NOT NULL,\n \"IsPrimary\" INTEGER NOT NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"UpdatedAt\" TEXT NOT NULL\n);\n\nINSERT INTO \"__EFMigrationsHistory\" (\"MigrationId\", \"ProductVersion\")\nVALUES ('20240729105618_1.1.0-AddPkiTables', '9.0.4');\n\nCREATE TABLE \"Settings\" (\n \"Key\" TEXT NOT NULL CONSTRAINT \"PK_Settings\" PRIMARY KEY,\n \"Value\" TEXT NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"UpdatedAt\" TEXT NOT NULL\n);\n\nINSERT INTO \"__EFMigrationsHistory\" (\"MigrationId\", \"ProductVersion\")\nVALUES ('20240805073413_1.2.0-AddSettingsTable', '9.0.4');\n\nCREATE TABLE \"ef_temp_Aliases\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_Aliases\" PRIMARY KEY,\n \"BirthDate\" TEXT NOT NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"Email\" TEXT NULL,\n \"FirstName\" VARCHAR NULL,\n \"Gender\" VARCHAR NULL,\n \"LastName\" VARCHAR NULL,\n \"NickName\" VARCHAR NULL,\n \"UpdatedAt\" TEXT NOT NULL\n);\n\nINSERT INTO \"ef_temp_Aliases\" (\"Id\", \"BirthDate\", \"CreatedAt\", \"Email\", \"FirstName\", \"Gender\", \"LastName\", \"NickName\", \"UpdatedAt\")\nSELECT \"Id\", \"BirthDate\", \"CreatedAt\", \"Email\", \"FirstName\", \"Gender\", \"LastName\", \"NickName\", \"UpdatedAt\"\nFROM \"Aliases\";\n\nCOMMIT;\n\nPRAGMA foreign_keys = 0;\n\nBEGIN TRANSACTION;\nDROP TABLE \"Aliases\";\n\nALTER TABLE \"ef_temp_Aliases\" RENAME TO \"Aliases\";\n\nCOMMIT;\n\nPRAGMA foreign_keys = 1;\n\nINSERT INTO \"__EFMigrationsHistory\" (\"MigrationId\", \"ProductVersion\")\nVALUES ('20240805122422_1.3.0-UpdateIdentityStructure', '9.0.4');\n\nBEGIN TRANSACTION;\nCREATE TABLE \"ef_temp_Credentials\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_Credentials\" PRIMARY KEY,\n \"AliasId\" TEXT NOT NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"Notes\" TEXT NULL,\n \"ServiceId\" TEXT NOT NULL,\n \"UpdatedAt\" TEXT NOT NULL,\n \"Username\" TEXT NULL,\n CONSTRAINT \"FK_Credentials_Aliases_AliasId\" FOREIGN KEY (\"AliasId\") REFERENCES \"Aliases\" (\"Id\") ON DELETE CASCADE,\n CONSTRAINT \"FK_Credentials_Services_ServiceId\" FOREIGN KEY (\"ServiceId\") REFERENCES \"Services\" (\"Id\") ON DELETE CASCADE\n);\n\nINSERT INTO \"ef_temp_Credentials\" (\"Id\", \"AliasId\", \"CreatedAt\", \"Notes\", \"ServiceId\", \"UpdatedAt\", \"Username\")\nSELECT \"Id\", \"AliasId\", \"CreatedAt\", \"Notes\", \"ServiceId\", \"UpdatedAt\", \"Username\"\nFROM \"Credentials\";\n\nCOMMIT;\n\nPRAGMA foreign_keys = 0;\n\nBEGIN TRANSACTION;\nDROP TABLE \"Credentials\";\n\nALTER TABLE \"ef_temp_Credentials\" RENAME TO \"Credentials\";\n\nCOMMIT;\n\nPRAGMA foreign_keys = 1;\n\nBEGIN TRANSACTION;\nCREATE INDEX \"IX_Credentials_AliasId\" ON \"Credentials\" (\"AliasId\");\n\nCREATE INDEX \"IX_Credentials_ServiceId\" ON \"Credentials\" (\"ServiceId\");\n\nCOMMIT;\n\nINSERT INTO \"__EFMigrationsHistory\" (\"MigrationId\", \"ProductVersion\")\nVALUES ('20240812141727_1.3.1-MakeUsernameOptional', '9.0.4');\n\nBEGIN TRANSACTION;\nALTER TABLE \"Settings\" ADD \"IsDeleted\" INTEGER NOT NULL DEFAULT 0;\n\nALTER TABLE \"Services\" ADD \"IsDeleted\" INTEGER NOT NULL DEFAULT 0;\n\nALTER TABLE \"Passwords\" ADD \"IsDeleted\" INTEGER NOT NULL DEFAULT 0;\n\nALTER TABLE \"EncryptionKeys\" ADD \"IsDeleted\" INTEGER NOT NULL DEFAULT 0;\n\nALTER TABLE \"Credentials\" ADD \"IsDeleted\" INTEGER NOT NULL DEFAULT 0;\n\nALTER TABLE \"Attachment\" ADD \"IsDeleted\" INTEGER NOT NULL DEFAULT 0;\n\nALTER TABLE \"Aliases\" ADD \"IsDeleted\" INTEGER NOT NULL DEFAULT 0;\n\nINSERT INTO \"__EFMigrationsHistory\" (\"MigrationId\", \"ProductVersion\")\nVALUES ('20240916105320_1.4.0-AddSyncSupport', '9.0.4');\n\nALTER TABLE \"Attachment\" RENAME TO \"Attachments\";\n\nCREATE TABLE \"ef_temp_Attachments\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_Attachments\" PRIMARY KEY,\n \"Blob\" BLOB NOT NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"CredentialId\" TEXT NOT NULL,\n \"Filename\" TEXT NOT NULL,\n \"IsDeleted\" INTEGER NOT NULL,\n \"UpdatedAt\" TEXT NOT NULL,\n CONSTRAINT \"FK_Attachments_Credentials_CredentialId\" FOREIGN KEY (\"CredentialId\") REFERENCES \"Credentials\" (\"Id\") ON DELETE CASCADE\n);\n\nINSERT INTO \"ef_temp_Attachments\" (\"Id\", \"Blob\", \"CreatedAt\", \"CredentialId\", \"Filename\", \"IsDeleted\", \"UpdatedAt\")\nSELECT \"Id\", \"Blob\", \"CreatedAt\", \"CredentialId\", \"Filename\", \"IsDeleted\", \"UpdatedAt\"\nFROM \"Attachments\";\n\nCOMMIT;\n\nPRAGMA foreign_keys = 0;\n\nBEGIN TRANSACTION;\nDROP TABLE \"Attachments\";\n\nALTER TABLE \"ef_temp_Attachments\" RENAME TO \"Attachments\";\n\nCOMMIT;\n\nPRAGMA foreign_keys = 1;\n\nBEGIN TRANSACTION;\nCREATE INDEX \"IX_Attachments_CredentialId\" ON \"Attachments\" (\"CredentialId\");\n\nCOMMIT;\n\nINSERT INTO \"__EFMigrationsHistory\" (\"MigrationId\", \"ProductVersion\")\nVALUES ('20240917191243_1.4.1-RenameAttachmentsPlural', '9.0.4');\n\nBEGIN TRANSACTION;\nCREATE TABLE \"TotpCodes\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_TotpCodes\" PRIMARY KEY,\n \"Name\" TEXT NOT NULL,\n \"SecretKey\" TEXT NOT NULL,\n \"CredentialId\" TEXT NOT NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"UpdatedAt\" TEXT NOT NULL,\n \"IsDeleted\" INTEGER NOT NULL,\n CONSTRAINT \"FK_TotpCodes_Credentials_CredentialId\" FOREIGN KEY (\"CredentialId\") REFERENCES \"Credentials\" (\"Id\") ON DELETE CASCADE\n);\n\nCREATE INDEX \"IX_TotpCodes_CredentialId\" ON \"TotpCodes\" (\"CredentialId\");\n\nINSERT INTO \"__EFMigrationsHistory\" (\"MigrationId\", \"ProductVersion\")\nVALUES ('20250310131554_1.5.0-AddTotpCodes', '9.0.4');\n\n\nPRAGMA foreign_keys = OFF;\n\n-- Clean up any existing temp tables first\nDROP TABLE IF EXISTS \"__EFMigrationsHistory_temp\";\nDROP TABLE IF EXISTS \"Aliases_temp\";\nDROP TABLE IF EXISTS \"Services_temp\";\nDROP TABLE IF EXISTS \"EncryptionKeys_temp\";\nDROP TABLE IF EXISTS \"Settings_temp\";\nDROP TABLE IF EXISTS \"Credentials_temp\";\nDROP TABLE IF EXISTS \"Attachments_temp\";\nDROP TABLE IF EXISTS \"Passwords_temp\";\nDROP TABLE IF EXISTS \"TotpCodes_temp\";\n\n-- Create backup tables for all data\nCREATE TABLE \"__EFMigrationsHistory_temp\" AS SELECT * FROM \"__EFMigrationsHistory\";\nCREATE TABLE \"Aliases_temp\" AS SELECT * FROM \"Aliases\";\nCREATE TABLE \"Services_temp\" AS SELECT * FROM \"Services\";\nCREATE TABLE \"EncryptionKeys_temp\" AS SELECT * FROM \"EncryptionKeys\";\nCREATE TABLE \"Settings_temp\" AS SELECT * FROM \"Settings\";\nCREATE TABLE \"Credentials_temp\" AS SELECT * FROM \"Credentials\";\nCREATE TABLE \"Attachments_temp\" AS SELECT * FROM \"Attachments\";\nCREATE TABLE \"Passwords_temp\" AS SELECT * FROM \"Passwords\";\nCREATE TABLE \"TotpCodes_temp\" AS SELECT * FROM \"TotpCodes\";\n\n-- Delete orphaned records that do not have a valid FK to the credential object\nDELETE FROM \"Attachments_temp\" WHERE \"CredentialId\" NOT IN (SELECT \"Id\" FROM \"Credentials_temp\");\nDELETE FROM \"Passwords_temp\" WHERE \"CredentialId\" NOT IN (SELECT \"Id\" FROM \"Credentials_temp\");\nDELETE FROM \"TotpCodes_temp\" WHERE \"CredentialId\" NOT IN (SELECT \"Id\" FROM \"Credentials_temp\");\n\n-- Delete orphaned credentials that do not have valid FKs to alias or service objects\nDELETE FROM \"Credentials_temp\" WHERE \"AliasId\" NOT IN (SELECT \"Id\" FROM \"Aliases_temp\");\nDELETE FROM \"Credentials_temp\" WHERE \"ServiceId\" NOT IN (SELECT \"Id\" FROM \"Services_temp\");\n\n-- After cleaning credentials, clean dependent tables again in case we removed credentials\nDELETE FROM \"Attachments_temp\" WHERE \"CredentialId\" NOT IN (SELECT \"Id\" FROM \"Credentials_temp\");\nDELETE FROM \"Passwords_temp\" WHERE \"CredentialId\" NOT IN (SELECT \"Id\" FROM \"Credentials_temp\");\nDELETE FROM \"TotpCodes_temp\" WHERE \"CredentialId\" NOT IN (SELECT \"Id\" FROM \"Credentials_temp\");\n\n-- Drop all existing tables\nDROP TABLE \"TotpCodes\";\nDROP TABLE \"Passwords\";\nDROP TABLE \"Attachments\";\nDROP TABLE \"Credentials\";\nDROP TABLE \"Settings\";\nDROP TABLE \"EncryptionKeys\";\nDROP TABLE \"Services\";\nDROP TABLE \"Aliases\";\nDROP TABLE \"__EFMigrationsHistory\";\n\n-- Recreate tables with proper constraints (no dependencies first)\nCREATE TABLE \"__EFMigrationsHistory\" (\n \"MigrationId\" TEXT NOT NULL CONSTRAINT \"PK___EFMigrationsHistory\" PRIMARY KEY,\n \"ProductVersion\" TEXT NOT NULL\n);\n\nCREATE TABLE \"Aliases\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_Aliases\" PRIMARY KEY,\n \"BirthDate\" TEXT NOT NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"Email\" TEXT NULL,\n \"FirstName\" VARCHAR NULL,\n \"Gender\" VARCHAR NULL,\n \"LastName\" VARCHAR NULL,\n \"NickName\" VARCHAR NULL,\n \"UpdatedAt\" TEXT NOT NULL,\n \"IsDeleted\" INTEGER NOT NULL DEFAULT 0\n);\n\nCREATE TABLE \"Services\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_Services\" PRIMARY KEY,\n \"Name\" TEXT NULL,\n \"Url\" TEXT NULL,\n \"Logo\" BLOB NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"UpdatedAt\" TEXT NOT NULL,\n \"IsDeleted\" INTEGER NOT NULL DEFAULT 0\n);\n\nCREATE TABLE \"EncryptionKeys\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_EncryptionKeys\" PRIMARY KEY,\n \"PublicKey\" TEXT NOT NULL,\n \"PrivateKey\" TEXT NOT NULL,\n \"IsPrimary\" INTEGER NOT NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"UpdatedAt\" TEXT NOT NULL,\n \"IsDeleted\" INTEGER NOT NULL DEFAULT 0\n);\n\nCREATE TABLE \"Settings\" (\n \"Key\" TEXT NOT NULL CONSTRAINT \"PK_Settings\" PRIMARY KEY,\n \"Value\" TEXT NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"UpdatedAt\" TEXT NOT NULL,\n \"IsDeleted\" INTEGER NOT NULL DEFAULT 0\n);\n\n-- Tables with foreign keys\nCREATE TABLE \"Credentials\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_Credentials\" PRIMARY KEY,\n \"AliasId\" TEXT NOT NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"Notes\" TEXT NULL,\n \"ServiceId\" TEXT NOT NULL,\n \"UpdatedAt\" TEXT NOT NULL,\n \"Username\" TEXT NULL,\n \"IsDeleted\" INTEGER NOT NULL DEFAULT 0,\n CONSTRAINT \"FK_Credentials_Aliases_AliasId\" FOREIGN KEY (\"AliasId\") REFERENCES \"Aliases\" (\"Id\") ON DELETE CASCADE,\n CONSTRAINT \"FK_Credentials_Services_ServiceId\" FOREIGN KEY (\"ServiceId\") REFERENCES \"Services\" (\"Id\") ON DELETE CASCADE\n);\n\nCREATE TABLE \"Attachments\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_Attachments\" PRIMARY KEY,\n \"Blob\" BLOB NOT NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"CredentialId\" TEXT NOT NULL,\n \"Filename\" TEXT NOT NULL,\n \"IsDeleted\" INTEGER NOT NULL DEFAULT 0,\n \"UpdatedAt\" TEXT NOT NULL,\n CONSTRAINT \"FK_Attachments_Credentials_CredentialId\" FOREIGN KEY (\"CredentialId\") REFERENCES \"Credentials\" (\"Id\") ON DELETE CASCADE\n);\n\nCREATE TABLE \"Passwords\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_Passwords\" PRIMARY KEY,\n \"Value\" TEXT NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"UpdatedAt\" TEXT NOT NULL,\n \"CredentialId\" TEXT NOT NULL,\n \"IsDeleted\" INTEGER NOT NULL DEFAULT 0,\n CONSTRAINT \"FK_Passwords_Credentials_CredentialId\" FOREIGN KEY (\"CredentialId\") REFERENCES \"Credentials\" (\"Id\") ON DELETE CASCADE\n);\n\nCREATE TABLE \"TotpCodes\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_TotpCodes\" PRIMARY KEY,\n \"Name\" TEXT NOT NULL,\n \"SecretKey\" TEXT NOT NULL,\n \"CredentialId\" TEXT NOT NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"UpdatedAt\" TEXT NOT NULL,\n \"IsDeleted\" INTEGER NOT NULL DEFAULT 0,\n CONSTRAINT \"FK_TotpCodes_Credentials_CredentialId\" FOREIGN KEY (\"CredentialId\") REFERENCES \"Credentials\" (\"Id\") ON DELETE CASCADE\n);\n\n\n-- Restore data from temp tables\nINSERT INTO \"__EFMigrationsHistory\" SELECT * FROM \"__EFMigrationsHistory_temp\";\nINSERT INTO \"Aliases\" SELECT * FROM \"Aliases_temp\";\nINSERT INTO \"Services\" SELECT * FROM \"Services_temp\";\nINSERT INTO \"EncryptionKeys\" SELECT * FROM \"EncryptionKeys_temp\";\nINSERT INTO \"Settings\" SELECT * FROM \"Settings_temp\";\nINSERT INTO \"Credentials\" SELECT * FROM \"Credentials_temp\";\nINSERT INTO \"Attachments\" SELECT * FROM \"Attachments_temp\";\nINSERT INTO \"Passwords\" SELECT * FROM \"Passwords_temp\";\nINSERT INTO \"TotpCodes\" SELECT * FROM \"TotpCodes_temp\";\n\n-- =====================================================================================\n-- Date Format Normalization Migration\n-- =====================================================================================\n-- This migration normalizes ALL date fields to the standard format: 'yyyy-MM-dd HH:mm:ss.fff'\n-- Previously the different clients used different date formats which complicate date parsing.\n-- From version 0.24.0 onwards, all new dates are stored in this standard format.\n\n-- Update Aliases table (CreatedAt, UpdatedAt, BirthDate)\nUPDATE \"Aliases\" SET \"CreatedAt\" =\n CASE\n -- Already in correct format (yyyy-MM-dd HH:mm:ss.fff) - no change\n WHEN \"CreatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9] [0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9][0-9][0-9]'\n THEN \"CreatedAt\"\n\n -- ISO 8601 with milliseconds (yyyy-MM-ddTHH:mm:ss.fffZ) -> Replace T with space, remove Z and everything after .fff\n WHEN \"CreatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]T[0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9]*'\n THEN substr(\"CreatedAt\", 1, 10) || ' ' || substr(\"CreatedAt\", 12, 12)\n\n -- Without milliseconds (yyyy-MM-dd HH:mm:ss or yyyy-MM-ddTHH:mm:ssZ) -> Add .000\n WHEN \"CreatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9][T ][0-9][0-9]:[0-9][0-9]:[0-9][0-9]*'\n THEN substr(\"CreatedAt\", 1, 10) || ' ' || substr(replace(\"CreatedAt\", 'T', ' '), 12, 8) || '.000'\n\n -- Fallback: if none match, keep as-is (edge case)\n ELSE \"CreatedAt\"\n END;\n\nUPDATE \"Aliases\" SET \"UpdatedAt\" =\n CASE\n WHEN \"UpdatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9] [0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9][0-9][0-9]'\n THEN \"UpdatedAt\"\n WHEN \"UpdatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]T[0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9]*'\n THEN substr(\"UpdatedAt\", 1, 10) || ' ' || substr(\"UpdatedAt\", 12, 12)\n WHEN \"UpdatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9][T ][0-9][0-9]:[0-9][0-9]:[0-9][0-9]*'\n THEN substr(\"UpdatedAt\", 1, 10) || ' ' || substr(replace(\"UpdatedAt\", 'T', ' '), 12, 8) || '.000'\n ELSE \"UpdatedAt\"\n END;\n\n-- BirthDate: Always set time to 00:00:00 (no milliseconds for birth dates)\nUPDATE \"Aliases\" SET \"BirthDate\" =\n CASE\n -- If empty or already '0001-01-01 00:00:00', keep as-is\n WHEN \"BirthDate\" = '' OR \"BirthDate\" = '0001-01-01 00:00:00'\n THEN \"BirthDate\"\n\n -- If already in correct format (yyyy-MM-dd 00:00:00), keep as-is\n WHEN \"BirthDate\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9] 00:00:00'\n THEN \"BirthDate\"\n\n -- Extract date part and set time to 00:00:00\n WHEN \"BirthDate\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]*'\n THEN substr(\"BirthDate\", 1, 10) || ' 00:00:00'\n\n -- Fallback\n ELSE \"BirthDate\"\n END;\n\n-- Update Services table (CreatedAt, UpdatedAt)\nUPDATE \"Services\" SET \"CreatedAt\" =\n CASE\n WHEN \"CreatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9] [0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9][0-9][0-9]'\n THEN \"CreatedAt\"\n WHEN \"CreatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]T[0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9]*'\n THEN substr(\"CreatedAt\", 1, 10) || ' ' || substr(\"CreatedAt\", 12, 12)\n WHEN \"CreatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9][T ][0-9][0-9]:[0-9][0-9]:[0-9][0-9]*'\n THEN substr(\"CreatedAt\", 1, 10) || ' ' || substr(replace(\"CreatedAt\", 'T', ' '), 12, 8) || '.000'\n ELSE \"CreatedAt\"\n END;\n\nUPDATE \"Services\" SET \"UpdatedAt\" =\n CASE\n WHEN \"UpdatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9] [0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9][0-9][0-9]'\n THEN \"UpdatedAt\"\n WHEN \"UpdatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]T[0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9]*'\n THEN substr(\"UpdatedAt\", 1, 10) || ' ' || substr(\"UpdatedAt\", 12, 12)\n WHEN \"UpdatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9][T ][0-9][0-9]:[0-9][0-9]:[0-9][0-9]*'\n THEN substr(\"UpdatedAt\", 1, 10) || ' ' || substr(replace(\"UpdatedAt\", 'T', ' '), 12, 8) || '.000'\n ELSE \"UpdatedAt\"\n END;\n\n-- Update EncryptionKeys table (CreatedAt, UpdatedAt)\nUPDATE \"EncryptionKeys\" SET \"CreatedAt\" =\n CASE\n WHEN \"CreatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9] [0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9][0-9][0-9]'\n THEN \"CreatedAt\"\n WHEN \"CreatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]T[0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9]*'\n THEN substr(\"CreatedAt\", 1, 10) || ' ' || substr(\"CreatedAt\", 12, 12)\n WHEN \"CreatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9][T ][0-9][0-9]:[0-9][0-9]:[0-9][0-9]*'\n THEN substr(\"CreatedAt\", 1, 10) || ' ' || substr(replace(\"CreatedAt\", 'T', ' '), 12, 8) || '.000'\n ELSE \"CreatedAt\"\n END;\n\nUPDATE \"EncryptionKeys\" SET \"UpdatedAt\" =\n CASE\n WHEN \"UpdatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9] [0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9][0-9][0-9]'\n THEN \"UpdatedAt\"\n WHEN \"UpdatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]T[0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9]*'\n THEN substr(\"UpdatedAt\", 1, 10) || ' ' || substr(\"UpdatedAt\", 12, 12)\n WHEN \"UpdatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9][T ][0-9][0-9]:[0-9][0-9]:[0-9][0-9]*'\n THEN substr(\"UpdatedAt\", 1, 10) || ' ' || substr(replace(\"UpdatedAt\", 'T', ' '), 12, 8) || '.000'\n ELSE \"UpdatedAt\"\n END;\n\n-- Update Settings table (CreatedAt, UpdatedAt)\nUPDATE \"Settings\" SET \"CreatedAt\" =\n CASE\n WHEN \"CreatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9] [0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9][0-9][0-9]'\n THEN \"CreatedAt\"\n WHEN \"CreatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]T[0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9]*'\n THEN substr(\"CreatedAt\", 1, 10) || ' ' || substr(\"CreatedAt\", 12, 12)\n WHEN \"CreatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9][T ][0-9][0-9]:[0-9][0-9]:[0-9][0-9]*'\n THEN substr(\"CreatedAt\", 1, 10) || ' ' || substr(replace(\"CreatedAt\", 'T', ' '), 12, 8) || '.000'\n ELSE \"CreatedAt\"\n END;\n\nUPDATE \"Settings\" SET \"UpdatedAt\" =\n CASE\n WHEN \"UpdatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9] [0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9][0-9][0-9]'\n THEN \"UpdatedAt\"\n WHEN \"UpdatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]T[0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9]*'\n THEN substr(\"UpdatedAt\", 1, 10) || ' ' || substr(\"UpdatedAt\", 12, 12)\n WHEN \"UpdatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9][T ][0-9][0-9]:[0-9][0-9]:[0-9][0-9]*'\n THEN substr(\"UpdatedAt\", 1, 10) || ' ' || substr(replace(\"UpdatedAt\", 'T', ' '), 12, 8) || '.000'\n ELSE \"UpdatedAt\"\n END;\n\n-- Update Credentials table (CreatedAt, UpdatedAt)\nUPDATE \"Credentials\" SET \"CreatedAt\" =\n CASE\n WHEN \"CreatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9] [0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9][0-9][0-9]'\n THEN \"CreatedAt\"\n WHEN \"CreatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]T[0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9]*'\n THEN substr(\"CreatedAt\", 1, 10) || ' ' || substr(\"CreatedAt\", 12, 12)\n WHEN \"CreatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9][T ][0-9][0-9]:[0-9][0-9]:[0-9][0-9]*'\n THEN substr(\"CreatedAt\", 1, 10) || ' ' || substr(replace(\"CreatedAt\", 'T', ' '), 12, 8) || '.000'\n ELSE \"CreatedAt\"\n END;\n\nUPDATE \"Credentials\" SET \"UpdatedAt\" =\n CASE\n WHEN \"UpdatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9] [0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9][0-9][0-9]'\n THEN \"UpdatedAt\"\n WHEN \"UpdatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]T[0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9]*'\n THEN substr(\"UpdatedAt\", 1, 10) || ' ' || substr(\"UpdatedAt\", 12, 12)\n WHEN \"UpdatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9][T ][0-9][0-9]:[0-9][0-9]:[0-9][0-9]*'\n THEN substr(\"UpdatedAt\", 1, 10) || ' ' || substr(replace(\"UpdatedAt\", 'T', ' '), 12, 8) || '.000'\n ELSE \"UpdatedAt\"\n END;\n\n-- Update Attachments table (CreatedAt, UpdatedAt)\nUPDATE \"Attachments\" SET \"CreatedAt\" =\n CASE\n WHEN \"CreatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9] [0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9][0-9][0-9]'\n THEN \"CreatedAt\"\n WHEN \"CreatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]T[0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9]*'\n THEN substr(\"CreatedAt\", 1, 10) || ' ' || substr(\"CreatedAt\", 12, 12)\n WHEN \"CreatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9][T ][0-9][0-9]:[0-9][0-9]:[0-9][0-9]*'\n THEN substr(\"CreatedAt\", 1, 10) || ' ' || substr(replace(\"CreatedAt\", 'T', ' '), 12, 8) || '.000'\n ELSE \"CreatedAt\"\n END;\n\nUPDATE \"Attachments\" SET \"UpdatedAt\" =\n CASE\n WHEN \"UpdatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9] [0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9][0-9][0-9]'\n THEN \"UpdatedAt\"\n WHEN \"UpdatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]T[0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9]*'\n THEN substr(\"UpdatedAt\", 1, 10) || ' ' || substr(\"UpdatedAt\", 12, 12)\n WHEN \"UpdatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9][T ][0-9][0-9]:[0-9][0-9]:[0-9][0-9]*'\n THEN substr(\"UpdatedAt\", 1, 10) || ' ' || substr(replace(\"UpdatedAt\", 'T', ' '), 12, 8) || '.000'\n ELSE \"UpdatedAt\"\n END;\n\n-- Update Passwords table (CreatedAt, UpdatedAt)\nUPDATE \"Passwords\" SET \"CreatedAt\" =\n CASE\n WHEN \"CreatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9] [0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9][0-9][0-9]'\n THEN \"CreatedAt\"\n WHEN \"CreatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]T[0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9]*'\n THEN substr(\"CreatedAt\", 1, 10) || ' ' || substr(\"CreatedAt\", 12, 12)\n WHEN \"CreatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9][T ][0-9][0-9]:[0-9][0-9]:[0-9][0-9]*'\n THEN substr(\"CreatedAt\", 1, 10) || ' ' || substr(replace(\"CreatedAt\", 'T', ' '), 12, 8) || '.000'\n ELSE \"CreatedAt\"\n END;\n\nUPDATE \"Passwords\" SET \"UpdatedAt\" =\n CASE\n WHEN \"UpdatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9] [0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9][0-9][0-9]'\n THEN \"UpdatedAt\"\n WHEN \"UpdatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]T[0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9]*'\n THEN substr(\"UpdatedAt\", 1, 10) || ' ' || substr(\"UpdatedAt\", 12, 12)\n WHEN \"UpdatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9][T ][0-9][0-9]:[0-9][0-9]:[0-9][0-9]*'\n THEN substr(\"UpdatedAt\", 1, 10) || ' ' || substr(replace(\"UpdatedAt\", 'T', ' '), 12, 8) || '.000'\n ELSE \"UpdatedAt\"\n END;\n\n-- Update TotpCodes table (CreatedAt, UpdatedAt)\nUPDATE \"TotpCodes\" SET \"CreatedAt\" =\n CASE\n WHEN \"CreatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9] [0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9][0-9][0-9]'\n THEN \"CreatedAt\"\n WHEN \"CreatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]T[0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9]*'\n THEN substr(\"CreatedAt\", 1, 10) || ' ' || substr(\"CreatedAt\", 12, 12)\n WHEN \"CreatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9][T ][0-9][0-9]:[0-9][0-9]:[0-9][0-9]*'\n THEN substr(\"CreatedAt\", 1, 10) || ' ' || substr(replace(\"CreatedAt\", 'T', ' '), 12, 8) || '.000'\n ELSE \"CreatedAt\"\n END;\n\nUPDATE \"TotpCodes\" SET \"UpdatedAt\" =\n CASE\n WHEN \"UpdatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9] [0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9][0-9][0-9]'\n THEN \"UpdatedAt\"\n WHEN \"UpdatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]T[0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9]*'\n THEN substr(\"UpdatedAt\", 1, 10) || ' ' || substr(\"UpdatedAt\", 12, 12)\n WHEN \"UpdatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9][T ][0-9][0-9]:[0-9][0-9]:[0-9][0-9]*'\n THEN substr(\"UpdatedAt\", 1, 10) || ' ' || substr(replace(\"UpdatedAt\", 'T', ' '), 12, 8) || '.000'\n ELSE \"UpdatedAt\"\n END;\n\n-- =====================================================================================\n-- End of Date Format Normalization Migration\n-- =====================================================================================\n\n-- Recreate indexes\nCREATE INDEX \"IX_Credentials_AliasId\" ON \"Credentials\" (\"AliasId\");\nCREATE INDEX \"IX_Credentials_ServiceId\" ON \"Credentials\" (\"ServiceId\");\nCREATE INDEX \"IX_Attachments_CredentialId\" ON \"Attachments\" (\"CredentialId\");\nCREATE INDEX \"IX_Passwords_CredentialId\" ON \"Passwords\" (\"CredentialId\");\nCREATE INDEX \"IX_TotpCodes_CredentialId\" ON \"TotpCodes\" (\"CredentialId\");\n\n-- Clean up temp tables\nDROP TABLE \"__EFMigrationsHistory_temp\";\nDROP TABLE \"Aliases_temp\";\nDROP TABLE \"Services_temp\";\nDROP TABLE \"EncryptionKeys_temp\";\nDROP TABLE \"Settings_temp\";\nDROP TABLE \"Credentials_temp\";\nDROP TABLE \"Attachments_temp\";\nDROP TABLE \"Passwords_temp\";\nDROP TABLE \"TotpCodes_temp\";\n\nPRAGMA foreign_keys = ON;\n\n\nCREATE TABLE \"Passkeys\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_Passkeys\" PRIMARY KEY,\n \"RpId\" TEXT COLLATE NOCASE NOT NULL,\n \"UserHandle\" BLOB NOT NULL,\n \"PublicKey\" TEXT NOT NULL,\n \"PrivateKey\" TEXT NOT NULL,\n \"PrfKey\" BLOB NULL,\n \"DisplayName\" TEXT NOT NULL,\n \"AdditionalData\" BLOB NULL,\n \"CredentialId\" TEXT NOT NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"UpdatedAt\" TEXT NOT NULL,\n \"IsDeleted\" INTEGER NOT NULL,\n CONSTRAINT \"FK_Passkeys_Credentials_CredentialId\" FOREIGN KEY (\"CredentialId\") REFERENCES \"Credentials\" (\"Id\") ON DELETE CASCADE\n);\n\nCREATE INDEX \"IX_Passkeys_CredentialId\" ON \"Passkeys\" (\"CredentialId\");\n\nCREATE INDEX \"IX_Passkeys_RpId\" ON \"Passkeys\" (\"RpId\");\n\nINSERT INTO \"__EFMigrationsHistory\" (\"MigrationId\", \"ProductVersion\")\nVALUES ('20251014122838_1.6.0-AddPasskeys', '9.0.4');\n\nALTER TABLE \"TotpCodes\" RENAME COLUMN \"CredentialId\" TO \"ItemId\";\n\nDROP INDEX IF EXISTS \"IX_TotpCodes_CredentialId\";\n\nCREATE INDEX IF NOT EXISTS \"IX_TotpCodes_ItemId\" ON \"TotpCodes\" (\"ItemId\");\n\nALTER TABLE \"Passkeys\" RENAME COLUMN \"CredentialId\" TO \"ItemId\";\n\nDROP INDEX IF EXISTS \"IX_Passkeys_CredentialId\";\n\nCREATE INDEX IF NOT EXISTS \"IX_Passkeys_ItemId\" ON \"Passkeys\" (\"ItemId\");\n\nALTER TABLE \"Attachments\" RENAME COLUMN \"CredentialId\" TO \"ItemId\";\n\nDROP INDEX IF EXISTS \"IX_Attachments_CredentialId\";\n\nCREATE INDEX IF NOT EXISTS \"IX_Attachments_ItemId\" ON \"Attachments\" (\"ItemId\");\n\nCREATE TABLE \"FieldDefinitions\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_FieldDefinitions\" PRIMARY KEY,\n \"FieldType\" TEXT NOT NULL,\n \"Label\" TEXT NOT NULL,\n \"IsMultiValue\" INTEGER NOT NULL,\n \"IsHidden\" INTEGER NOT NULL,\n \"EnableHistory\" INTEGER NOT NULL,\n \"Weight\" INTEGER NOT NULL,\n \"ApplicableToTypes\" TEXT NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"UpdatedAt\" TEXT NOT NULL,\n \"IsDeleted\" INTEGER NOT NULL\n);\n\nCREATE TABLE \"Folders\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_Folders\" PRIMARY KEY,\n \"Name\" TEXT NOT NULL,\n \"ParentFolderId\" TEXT NULL,\n \"Weight\" INTEGER NOT NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"UpdatedAt\" TEXT NOT NULL,\n \"IsDeleted\" INTEGER NOT NULL,\n CONSTRAINT \"FK_Folders_Folders_ParentFolderId\" FOREIGN KEY (\"ParentFolderId\") REFERENCES \"Folders\" (\"Id\") ON DELETE CASCADE\n);\n\nCREATE TABLE \"Logos\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_Logos\" PRIMARY KEY,\n \"Source\" TEXT NOT NULL,\n \"FileData\" BLOB NULL,\n \"MimeType\" TEXT NULL,\n \"FetchedAt\" TEXT NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"UpdatedAt\" TEXT NOT NULL,\n \"IsDeleted\" INTEGER NOT NULL\n);\n\nCREATE TABLE \"Tags\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_Tags\" PRIMARY KEY,\n \"Name\" TEXT NOT NULL,\n \"Color\" TEXT NULL,\n \"DisplayOrder\" INTEGER NOT NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"UpdatedAt\" TEXT NOT NULL,\n \"IsDeleted\" INTEGER NOT NULL\n);\n\nCREATE TABLE \"Items\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_Items\" PRIMARY KEY,\n \"Name\" TEXT NULL,\n \"ItemType\" TEXT NOT NULL,\n \"LogoId\" TEXT NULL,\n \"DeletedAt\" TEXT NULL,\n \"FolderId\" TEXT NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"UpdatedAt\" TEXT NOT NULL,\n \"IsDeleted\" INTEGER NOT NULL,\n CONSTRAINT \"FK_Items_Folders_FolderId\" FOREIGN KEY (\"FolderId\") REFERENCES \"Folders\" (\"Id\") ON DELETE SET NULL,\n CONSTRAINT \"FK_Items_Logos_LogoId\" FOREIGN KEY (\"LogoId\") REFERENCES \"Logos\" (\"Id\") ON DELETE SET NULL\n);\n\nCREATE TABLE \"FieldHistories\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_FieldHistories\" PRIMARY KEY,\n \"ItemId\" TEXT NOT NULL,\n \"FieldDefinitionId\" TEXT NULL,\n \"FieldKey\" TEXT NULL,\n \"ValueSnapshot\" TEXT NOT NULL,\n \"ChangedAt\" TEXT NOT NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"UpdatedAt\" TEXT NOT NULL,\n \"IsDeleted\" INTEGER NOT NULL,\n CONSTRAINT \"FK_FieldHistories_FieldDefinitions_FieldDefinitionId\" FOREIGN KEY (\"FieldDefinitionId\") REFERENCES \"FieldDefinitions\" (\"Id\") ON DELETE CASCADE,\n CONSTRAINT \"FK_FieldHistories_Items_ItemId\" FOREIGN KEY (\"ItemId\") REFERENCES \"Items\" (\"Id\") ON DELETE CASCADE\n);\n\nCREATE TABLE \"FieldValues\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_FieldValues\" PRIMARY KEY,\n \"ItemId\" TEXT NOT NULL,\n \"FieldDefinitionId\" TEXT NULL,\n \"FieldKey\" TEXT NULL,\n \"Value\" TEXT NULL,\n \"Weight\" INTEGER NOT NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"UpdatedAt\" TEXT NOT NULL,\n \"IsDeleted\" INTEGER NOT NULL,\n CONSTRAINT \"FK_FieldValues_FieldDefinitions_FieldDefinitionId\" FOREIGN KEY (\"FieldDefinitionId\") REFERENCES \"FieldDefinitions\" (\"Id\") ON DELETE CASCADE,\n CONSTRAINT \"FK_FieldValues_Items_ItemId\" FOREIGN KEY (\"ItemId\") REFERENCES \"Items\" (\"Id\") ON DELETE CASCADE\n);\n\nCREATE TABLE \"ItemTags\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_ItemTags\" PRIMARY KEY,\n \"ItemId\" TEXT NOT NULL,\n \"TagId\" TEXT NOT NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"UpdatedAt\" TEXT NOT NULL,\n \"IsDeleted\" INTEGER NOT NULL,\n CONSTRAINT \"FK_ItemTags_Items_ItemId\" FOREIGN KEY (\"ItemId\") REFERENCES \"Items\" (\"Id\") ON DELETE CASCADE,\n CONSTRAINT \"FK_ItemTags_Tags_TagId\" FOREIGN KEY (\"TagId\") REFERENCES \"Tags\" (\"Id\") ON DELETE CASCADE\n);\n\nCREATE INDEX \"IX_FieldHistories_FieldDefinitionId\" ON \"FieldHistories\" (\"FieldDefinitionId\");\n\nCREATE INDEX \"IX_FieldHistories_ItemId\" ON \"FieldHistories\" (\"ItemId\");\n\nCREATE INDEX \"IX_FieldValues_FieldDefinitionId\" ON \"FieldValues\" (\"FieldDefinitionId\");\n\nCREATE INDEX \"IX_FieldValues_FieldKey\" ON \"FieldValues\" (\"FieldKey\");\n\nCREATE INDEX \"IX_FieldValues_ItemId\" ON \"FieldValues\" (\"ItemId\");\n\nCREATE INDEX \"IX_FieldValues_ItemId_FieldDefinitionId_Weight\" ON \"FieldValues\" (\"ItemId\", \"FieldDefinitionId\", \"Weight\");\n\nCREATE INDEX \"IX_FieldValues_ItemId_FieldKey\" ON \"FieldValues\" (\"ItemId\", \"FieldKey\");\n\nCREATE INDEX \"IX_Folders_ParentFolderId\" ON \"Folders\" (\"ParentFolderId\");\n\nCREATE INDEX \"IX_Items_FolderId\" ON \"Items\" (\"FolderId\");\n\nCREATE INDEX \"IX_Items_LogoId\" ON \"Items\" (\"LogoId\");\n\nCREATE INDEX \"IX_ItemTags_ItemId\" ON \"ItemTags\" (\"ItemId\");\n\nCREATE UNIQUE INDEX \"IX_ItemTags_ItemId_TagId\" ON \"ItemTags\" (\"ItemId\", \"TagId\");\n\nCREATE INDEX \"IX_ItemTags_TagId\" ON \"ItemTags\" (\"TagId\");\n\nCREATE UNIQUE INDEX \"IX_Logos_Source\" ON \"Logos\" (\"Source\");\n\nCREATE INDEX \"IX_Tags_Name\" ON \"Tags\" (\"Name\");\n\n\n INSERT INTO Items (Id, Name, ItemType, LogoId, FolderId, CreatedAt, UpdatedAt, IsDeleted)\n SELECT\n c.Id,\n s.Name AS Name,\n CASE\n WHEN a.Id IS NOT NULL AND (\n (a.FirstName IS NOT NULL AND a.FirstName != '') OR\n (a.LastName IS NOT NULL AND a.LastName != '') OR\n (a.Gender IS NOT NULL AND a.Gender != '') OR\n (a.BirthDate IS NOT NULL AND a.BirthDate != '' AND a.BirthDate NOT LIKE '0001-%')\n ) THEN 'Alias'\n ELSE 'Login'\n END AS ItemType,\n NULL AS LogoId,\n NULL AS FolderId,\n c.CreatedAt,\n c.UpdatedAt,\n c.IsDeleted\n FROM Credentials c\n LEFT JOIN Services s ON s.Id = c.ServiceId\n LEFT JOIN Aliases a ON a.Id = c.AliasId;\n \n\n\n INSERT INTO Logos (Id, Source, FileData, MimeType, FetchedAt, CreatedAt, UpdatedAt, IsDeleted)\n SELECT\n UPPER(SUBSTR(hex(randomblob(4)), 1, 8) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(6)), 1, 12)) AS Id,\n -- Extract and normalize hostname: remove protocol, path, lowercase, and www. prefix\n REPLACE(\n LOWER(\n SUBSTR(\n CASE\n WHEN s.Url LIKE 'https://%' THEN SUBSTR(s.Url, 9)\n WHEN s.Url LIKE 'http://%' THEN SUBSTR(s.Url, 8)\n ELSE s.Url\n END,\n 1,\n CASE\n WHEN INSTR(\n CASE\n WHEN s.Url LIKE 'https://%' THEN SUBSTR(s.Url, 9)\n WHEN s.Url LIKE 'http://%' THEN SUBSTR(s.Url, 8)\n ELSE s.Url\n END, '/') > 0\n THEN INSTR(\n CASE\n WHEN s.Url LIKE 'https://%' THEN SUBSTR(s.Url, 9)\n WHEN s.Url LIKE 'http://%' THEN SUBSTR(s.Url, 8)\n ELSE s.Url\n END, '/') - 1\n ELSE LENGTH(\n CASE\n WHEN s.Url LIKE 'https://%' THEN SUBSTR(s.Url, 9)\n WHEN s.Url LIKE 'http://%' THEN SUBSTR(s.Url, 8)\n ELSE s.Url\n END)\n END\n )\n ),\n 'www.', ''\n ) AS Source,\n s.Logo AS FileData,\n 'image/png' AS MimeType,\n NULL AS FetchedAt,\n MIN(s.CreatedAt) AS CreatedAt,\n MAX(s.UpdatedAt) AS UpdatedAt,\n 0 AS IsDeleted\n FROM Services s\n WHERE s.Logo IS NOT NULL AND s.Url IS NOT NULL AND s.Url != ''\n GROUP BY REPLACE(\n LOWER(\n SUBSTR(\n CASE\n WHEN s.Url LIKE 'https://%' THEN SUBSTR(s.Url, 9)\n WHEN s.Url LIKE 'http://%' THEN SUBSTR(s.Url, 8)\n ELSE s.Url\n END,\n 1,\n CASE\n WHEN INSTR(\n CASE\n WHEN s.Url LIKE 'https://%' THEN SUBSTR(s.Url, 9)\n WHEN s.Url LIKE 'http://%' THEN SUBSTR(s.Url, 8)\n ELSE s.Url\n END, '/') > 0\n THEN INSTR(\n CASE\n WHEN s.Url LIKE 'https://%' THEN SUBSTR(s.Url, 9)\n WHEN s.Url LIKE 'http://%' THEN SUBSTR(s.Url, 8)\n ELSE s.Url\n END, '/') - 1\n ELSE LENGTH(\n CASE\n WHEN s.Url LIKE 'https://%' THEN SUBSTR(s.Url, 9)\n WHEN s.Url LIKE 'http://%' THEN SUBSTR(s.Url, 8)\n ELSE s.Url\n END)\n END\n )\n ),\n 'www.', ''\n );\n \n\n\n UPDATE Items\n SET LogoId = (\n SELECT l.Id FROM Logos l\n INNER JOIN Services s ON REPLACE(\n LOWER(\n SUBSTR(\n CASE\n WHEN s.Url LIKE 'https://%' THEN SUBSTR(s.Url, 9)\n WHEN s.Url LIKE 'http://%' THEN SUBSTR(s.Url, 8)\n ELSE s.Url\n END,\n 1,\n CASE\n WHEN INSTR(\n CASE\n WHEN s.Url LIKE 'https://%' THEN SUBSTR(s.Url, 9)\n WHEN s.Url LIKE 'http://%' THEN SUBSTR(s.Url, 8)\n ELSE s.Url\n END, '/') > 0\n THEN INSTR(\n CASE\n WHEN s.Url LIKE 'https://%' THEN SUBSTR(s.Url, 9)\n WHEN s.Url LIKE 'http://%' THEN SUBSTR(s.Url, 8)\n ELSE s.Url\n END, '/') - 1\n ELSE LENGTH(\n CASE\n WHEN s.Url LIKE 'https://%' THEN SUBSTR(s.Url, 9)\n WHEN s.Url LIKE 'http://%' THEN SUBSTR(s.Url, 8)\n ELSE s.Url\n END)\n END\n )\n ),\n 'www.', ''\n ) = l.Source\n INNER JOIN Credentials c ON c.ServiceId = s.Id\n WHERE c.Id = Items.Id\n LIMIT 1\n )\n WHERE EXISTS (\n SELECT 1 FROM Credentials c\n INNER JOIN Services s ON s.Id = c.ServiceId\n WHERE c.Id = Items.Id AND s.Logo IS NOT NULL\n );\n \n\n\n INSERT INTO FieldValues (Id, ItemId, FieldDefinitionId, FieldKey, Value, Weight, CreatedAt, UpdatedAt, IsDeleted)\n SELECT\n UPPER(SUBSTR(hex(randomblob(4)), 1, 8) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(6)), 1, 12)) AS Id,\n c.Id AS ItemId,\n NULL AS FieldDefinitionId,\n 'login.url' AS FieldKey,\n s.Url AS Value,\n 0 AS Weight,\n s.UpdatedAt AS CreatedAt,\n s.UpdatedAt AS UpdatedAt,\n 0 AS IsDeleted\n FROM Credentials c\n INNER JOIN Services s ON s.Id = c.ServiceId\n WHERE s.Url IS NOT NULL AND s.Url != '';\n \n\n\n INSERT INTO FieldValues (Id, ItemId, FieldDefinitionId, FieldKey, Value, Weight, CreatedAt, UpdatedAt, IsDeleted)\n SELECT\n UPPER(SUBSTR(hex(randomblob(4)), 1, 8) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(6)), 1, 12)) AS Id,\n c.Id AS ItemId,\n NULL AS FieldDefinitionId,\n 'login.username' AS FieldKey,\n c.Username AS Value,\n 0 AS Weight,\n c.UpdatedAt AS CreatedAt,\n c.UpdatedAt AS UpdatedAt,\n 0 AS IsDeleted\n FROM Credentials c\n WHERE c.Username IS NOT NULL AND c.Username != '';\n \n\n\n INSERT INTO FieldValues (Id, ItemId, FieldDefinitionId, FieldKey, Value, Weight, CreatedAt, UpdatedAt, IsDeleted)\n SELECT\n UPPER(SUBSTR(hex(randomblob(4)), 1, 8) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(6)), 1, 12)) AS Id,\n c.Id AS ItemId,\n NULL AS FieldDefinitionId,\n 'login.notes' AS FieldKey,\n c.Notes AS Value,\n 0 AS Weight,\n c.UpdatedAt AS CreatedAt,\n c.UpdatedAt AS UpdatedAt,\n 0 AS IsDeleted\n FROM Credentials c\n WHERE c.Notes IS NOT NULL AND c.Notes != '';\n \n\n\n INSERT INTO FieldValues (Id, ItemId, FieldDefinitionId, FieldKey, Value, Weight, CreatedAt, UpdatedAt, IsDeleted)\n SELECT\n UPPER(SUBSTR(hex(randomblob(4)), 1, 8) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(6)), 1, 12)) AS Id,\n p.CredentialId AS ItemId,\n NULL AS FieldDefinitionId,\n 'login.password' AS FieldKey,\n p.Value AS Value,\n 0 AS Weight,\n p.UpdatedAt AS CreatedAt,\n p.UpdatedAt AS UpdatedAt,\n 0 AS IsDeleted\n FROM Passwords p\n INNER JOIN (\n SELECT CredentialId, MAX(UpdatedAt) AS MaxUpdated, MAX(Id) AS MaxId\n FROM Passwords\n WHERE IsDeleted = 0\n GROUP BY CredentialId\n ) pm ON p.CredentialId = pm.CredentialId AND p.UpdatedAt = pm.MaxUpdated AND p.Id = pm.MaxId\n WHERE p.IsDeleted = 0;\n \n\n\n INSERT INTO FieldValues (Id, ItemId, FieldDefinitionId, FieldKey, Value, Weight, CreatedAt, UpdatedAt, IsDeleted)\n SELECT\n UPPER(SUBSTR(hex(randomblob(4)), 1, 8) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(6)), 1, 12)) AS Id,\n c.Id AS ItemId,\n NULL AS FieldDefinitionId,\n 'login.email' AS FieldKey,\n a.Email AS Value,\n 0 AS Weight,\n a.UpdatedAt AS CreatedAt,\n a.UpdatedAt AS UpdatedAt,\n 0 AS IsDeleted\n FROM Credentials c\n INNER JOIN Aliases a ON a.Id = c.AliasId\n WHERE a.Email IS NOT NULL AND a.Email != '';\n \n\n\n INSERT INTO FieldValues (Id, ItemId, FieldDefinitionId, FieldKey, Value, Weight, CreatedAt, UpdatedAt, IsDeleted)\n SELECT\n UPPER(SUBSTR(hex(randomblob(4)), 1, 8) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(6)), 1, 12)) AS Id,\n c.Id AS ItemId,\n NULL AS FieldDefinitionId,\n 'alias.first_name' AS FieldKey,\n a.FirstName AS Value,\n 0 AS Weight,\n a.UpdatedAt AS CreatedAt,\n a.UpdatedAt AS UpdatedAt,\n 0 AS IsDeleted\n FROM Credentials c\n INNER JOIN Aliases a ON a.Id = c.AliasId\n WHERE a.FirstName IS NOT NULL AND a.FirstName != '';\n \n\n\n INSERT INTO FieldValues (Id, ItemId, FieldDefinitionId, FieldKey, Value, Weight, CreatedAt, UpdatedAt, IsDeleted)\n SELECT\n UPPER(SUBSTR(hex(randomblob(4)), 1, 8) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(6)), 1, 12)) AS Id,\n c.Id AS ItemId,\n NULL AS FieldDefinitionId,\n 'alias.last_name' AS FieldKey,\n a.LastName AS Value,\n 0 AS Weight,\n a.UpdatedAt AS CreatedAt,\n a.UpdatedAt AS UpdatedAt,\n 0 AS IsDeleted\n FROM Credentials c\n INNER JOIN Aliases a ON a.Id = c.AliasId\n WHERE a.LastName IS NOT NULL AND a.LastName != '';\n \n\n\n INSERT INTO FieldValues (Id, ItemId, FieldDefinitionId, FieldKey, Value, Weight, CreatedAt, UpdatedAt, IsDeleted)\n SELECT\n UPPER(SUBSTR(hex(randomblob(4)), 1, 8) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(6)), 1, 12)) AS Id,\n c.Id AS ItemId,\n NULL AS FieldDefinitionId,\n 'alias.gender' AS FieldKey,\n a.Gender AS Value,\n 0 AS Weight,\n a.UpdatedAt AS CreatedAt,\n a.UpdatedAt AS UpdatedAt,\n 0 AS IsDeleted\n FROM Credentials c\n INNER JOIN Aliases a ON a.Id = c.AliasId\n WHERE a.Gender IS NOT NULL AND a.Gender != '';\n \n\n\n INSERT INTO FieldValues (Id, ItemId, FieldDefinitionId, FieldKey, Value, Weight, CreatedAt, UpdatedAt, IsDeleted)\n SELECT\n UPPER(SUBSTR(hex(randomblob(4)), 1, 8) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(6)), 1, 12)) AS Id,\n c.Id AS ItemId,\n NULL AS FieldDefinitionId,\n 'alias.birthdate' AS FieldKey,\n SUBSTR(a.BirthDate, 1, 10) AS Value,\n 0 AS Weight,\n a.UpdatedAt AS CreatedAt,\n a.UpdatedAt AS UpdatedAt,\n 0 AS IsDeleted\n FROM Credentials c\n INNER JOIN Aliases a ON a.Id = c.AliasId\n WHERE a.BirthDate IS NOT NULL AND a.BirthDate != '' AND a.BirthDate NOT LIKE '0001-%';\n \n\nDROP TABLE \"Passwords\";\n\nDROP TABLE \"Credentials\";\n\nDROP TABLE \"Aliases\";\n\nDROP TABLE \"Services\";\n\nCREATE TABLE \"ef_temp_Attachments\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_Attachments\" PRIMARY KEY,\n \"Blob\" BLOB NOT NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"Filename\" TEXT NOT NULL,\n \"IsDeleted\" INTEGER NOT NULL,\n \"ItemId\" TEXT NOT NULL,\n \"UpdatedAt\" TEXT NOT NULL,\n CONSTRAINT \"FK_Attachments_Items_ItemId\" FOREIGN KEY (\"ItemId\") REFERENCES \"Items\" (\"Id\") ON DELETE CASCADE\n);\n\nINSERT INTO \"ef_temp_Attachments\" (\"Id\", \"Blob\", \"CreatedAt\", \"Filename\", \"IsDeleted\", \"ItemId\", \"UpdatedAt\")\nSELECT \"Id\", \"Blob\", \"CreatedAt\", \"Filename\", \"IsDeleted\", \"ItemId\", \"UpdatedAt\"\nFROM \"Attachments\";\n\nCREATE TABLE \"ef_temp_Passkeys\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_Passkeys\" PRIMARY KEY,\n \"AdditionalData\" BLOB NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"DisplayName\" TEXT NOT NULL,\n \"IsDeleted\" INTEGER NOT NULL,\n \"ItemId\" TEXT NOT NULL,\n \"PrfKey\" BLOB NULL,\n \"PrivateKey\" TEXT NOT NULL,\n \"PublicKey\" TEXT NOT NULL,\n \"RpId\" TEXT COLLATE NOCASE NOT NULL,\n \"UpdatedAt\" TEXT NOT NULL,\n \"UserHandle\" BLOB NOT NULL,\n CONSTRAINT \"FK_Passkeys_Items_ItemId\" FOREIGN KEY (\"ItemId\") REFERENCES \"Items\" (\"Id\") ON DELETE CASCADE\n);\n\nINSERT INTO \"ef_temp_Passkeys\" (\"Id\", \"AdditionalData\", \"CreatedAt\", \"DisplayName\", \"IsDeleted\", \"ItemId\", \"PrfKey\", \"PrivateKey\", \"PublicKey\", \"RpId\", \"UpdatedAt\", \"UserHandle\")\nSELECT \"Id\", \"AdditionalData\", \"CreatedAt\", \"DisplayName\", \"IsDeleted\", \"ItemId\", \"PrfKey\", \"PrivateKey\", \"PublicKey\", \"RpId\", \"UpdatedAt\", \"UserHandle\"\nFROM \"Passkeys\";\n\nCREATE TABLE \"ef_temp_TotpCodes\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_TotpCodes\" PRIMARY KEY,\n \"CreatedAt\" TEXT NOT NULL,\n \"IsDeleted\" INTEGER NOT NULL,\n \"ItemId\" TEXT NOT NULL,\n \"Name\" TEXT NOT NULL,\n \"SecretKey\" TEXT NOT NULL,\n \"UpdatedAt\" TEXT NOT NULL,\n CONSTRAINT \"FK_TotpCodes_Items_ItemId\" FOREIGN KEY (\"ItemId\") REFERENCES \"Items\" (\"Id\") ON DELETE CASCADE\n);\n\nINSERT INTO \"ef_temp_TotpCodes\" (\"Id\", \"CreatedAt\", \"IsDeleted\", \"ItemId\", \"Name\", \"SecretKey\", \"UpdatedAt\")\nSELECT \"Id\", \"CreatedAt\", \"IsDeleted\", \"ItemId\", \"Name\", \"SecretKey\", \"UpdatedAt\"\nFROM \"TotpCodes\";\n\nCOMMIT;\n\nPRAGMA foreign_keys = 0;\n\nBEGIN TRANSACTION;\nDROP TABLE \"Attachments\";\n\nALTER TABLE \"ef_temp_Attachments\" RENAME TO \"Attachments\";\n\nDROP TABLE \"Passkeys\";\n\nALTER TABLE \"ef_temp_Passkeys\" RENAME TO \"Passkeys\";\n\nDROP TABLE \"TotpCodes\";\n\nALTER TABLE \"ef_temp_TotpCodes\" RENAME TO \"TotpCodes\";\n\nCOMMIT;\n\nPRAGMA foreign_keys = 1;\n\nBEGIN TRANSACTION;\nCREATE INDEX \"IX_Attachments_ItemId\" ON \"Attachments\" (\"ItemId\");\n\nCREATE INDEX \"IX_Passkeys_ItemId\" ON \"Passkeys\" (\"ItemId\");\n\nCREATE INDEX \"IX_Passkeys_RpId\" ON \"Passkeys\" (\"RpId\");\n\nCREATE INDEX \"IX_TotpCodes_ItemId\" ON \"TotpCodes\" (\"ItemId\");\n\nCOMMIT;\n\nINSERT INTO \"__EFMigrationsHistory\" (\"MigrationId\", \"ProductVersion\")\nVALUES ('20251213111207_1.7.0-FieldBasedDataModelUpdate', '9.0.4');\n"; +declare const COMPLETE_SCHEMA_SQL = "\n\uFEFFCREATE TABLE IF NOT EXISTS \"__EFMigrationsHistory\" (\n \"MigrationId\" TEXT NOT NULL CONSTRAINT \"PK___EFMigrationsHistory\" PRIMARY KEY,\n \"ProductVersion\" TEXT NOT NULL\n);\n\nBEGIN TRANSACTION;\nCREATE TABLE \"Aliases\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_Aliases\" PRIMARY KEY,\n \"Gender\" VARCHAR NULL,\n \"FirstName\" VARCHAR NULL,\n \"LastName\" VARCHAR NULL,\n \"NickName\" VARCHAR NULL,\n \"BirthDate\" TEXT NOT NULL,\n \"AddressStreet\" VARCHAR NULL,\n \"AddressCity\" VARCHAR NULL,\n \"AddressState\" VARCHAR NULL,\n \"AddressZipCode\" VARCHAR NULL,\n \"AddressCountry\" VARCHAR NULL,\n \"Hobbies\" TEXT NULL,\n \"EmailPrefix\" TEXT NULL,\n \"PhoneMobile\" TEXT NULL,\n \"BankAccountIBAN\" TEXT NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"UpdatedAt\" TEXT NOT NULL\n);\n\nCREATE TABLE \"Services\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_Services\" PRIMARY KEY,\n \"Name\" TEXT NULL,\n \"Url\" TEXT NULL,\n \"Logo\" BLOB NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"UpdatedAt\" TEXT NOT NULL\n);\n\nCREATE TABLE \"Credentials\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_Credentials\" PRIMARY KEY,\n \"AliasId\" TEXT NOT NULL,\n \"Notes\" TEXT NULL,\n \"Username\" TEXT NOT NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"UpdatedAt\" TEXT NOT NULL,\n \"ServiceId\" TEXT NOT NULL,\n CONSTRAINT \"FK_Credentials_Aliases_AliasId\" FOREIGN KEY (\"AliasId\") REFERENCES \"Aliases\" (\"Id\") ON DELETE CASCADE,\n CONSTRAINT \"FK_Credentials_Services_ServiceId\" FOREIGN KEY (\"ServiceId\") REFERENCES \"Services\" (\"Id\") ON DELETE CASCADE\n);\n\nCREATE TABLE \"Attachment\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_Attachment\" PRIMARY KEY,\n \"Filename\" TEXT NOT NULL,\n \"Blob\" BLOB NOT NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"UpdatedAt\" TEXT NOT NULL,\n \"CredentialId\" TEXT NOT NULL,\n CONSTRAINT \"FK_Attachment_Credentials_CredentialId\" FOREIGN KEY (\"CredentialId\") REFERENCES \"Credentials\" (\"Id\") ON DELETE CASCADE\n);\n\nCREATE TABLE \"Passwords\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_Passwords\" PRIMARY KEY,\n \"Value\" TEXT NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"UpdatedAt\" TEXT NOT NULL,\n \"CredentialId\" TEXT NOT NULL,\n CONSTRAINT \"FK_Passwords_Credentials_CredentialId\" FOREIGN KEY (\"CredentialId\") REFERENCES \"Credentials\" (\"Id\") ON DELETE CASCADE\n);\n\nCREATE INDEX \"IX_Attachment_CredentialId\" ON \"Attachment\" (\"CredentialId\");\n\nCREATE INDEX \"IX_Credentials_AliasId\" ON \"Credentials\" (\"AliasId\");\n\nCREATE INDEX \"IX_Credentials_ServiceId\" ON \"Credentials\" (\"ServiceId\");\n\nCREATE INDEX \"IX_Passwords_CredentialId\" ON \"Passwords\" (\"CredentialId\");\n\nINSERT INTO \"__EFMigrationsHistory\" (\"MigrationId\", \"ProductVersion\")\nVALUES ('20240708094944_1.0.0-InitialMigration', '9.0.4');\n\nINSERT INTO \"__EFMigrationsHistory\" (\"MigrationId\", \"ProductVersion\")\nVALUES ('20240708224522_1.0.1-EmptyTestMigration', '9.0.4');\n\nALTER TABLE \"Aliases\" RENAME COLUMN \"EmailPrefix\" TO \"Email\";\n\nINSERT INTO \"__EFMigrationsHistory\" (\"MigrationId\", \"ProductVersion\")\nVALUES ('20240711204207_1.0.2-ChangeEmailColumn', '9.0.4');\n\nCREATE TABLE \"EncryptionKeys\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_EncryptionKeys\" PRIMARY KEY,\n \"PublicKey\" TEXT NOT NULL,\n \"PrivateKey\" TEXT NOT NULL,\n \"IsPrimary\" INTEGER NOT NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"UpdatedAt\" TEXT NOT NULL\n);\n\nINSERT INTO \"__EFMigrationsHistory\" (\"MigrationId\", \"ProductVersion\")\nVALUES ('20240729105618_1.1.0-AddPkiTables', '9.0.4');\n\nCREATE TABLE \"Settings\" (\n \"Key\" TEXT NOT NULL CONSTRAINT \"PK_Settings\" PRIMARY KEY,\n \"Value\" TEXT NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"UpdatedAt\" TEXT NOT NULL\n);\n\nINSERT INTO \"__EFMigrationsHistory\" (\"MigrationId\", \"ProductVersion\")\nVALUES ('20240805073413_1.2.0-AddSettingsTable', '9.0.4');\n\nCREATE TABLE \"ef_temp_Aliases\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_Aliases\" PRIMARY KEY,\n \"BirthDate\" TEXT NOT NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"Email\" TEXT NULL,\n \"FirstName\" VARCHAR NULL,\n \"Gender\" VARCHAR NULL,\n \"LastName\" VARCHAR NULL,\n \"NickName\" VARCHAR NULL,\n \"UpdatedAt\" TEXT NOT NULL\n);\n\nINSERT INTO \"ef_temp_Aliases\" (\"Id\", \"BirthDate\", \"CreatedAt\", \"Email\", \"FirstName\", \"Gender\", \"LastName\", \"NickName\", \"UpdatedAt\")\nSELECT \"Id\", \"BirthDate\", \"CreatedAt\", \"Email\", \"FirstName\", \"Gender\", \"LastName\", \"NickName\", \"UpdatedAt\"\nFROM \"Aliases\";\n\nCOMMIT;\n\nPRAGMA foreign_keys = 0;\n\nBEGIN TRANSACTION;\nDROP TABLE \"Aliases\";\n\nALTER TABLE \"ef_temp_Aliases\" RENAME TO \"Aliases\";\n\nCOMMIT;\n\nPRAGMA foreign_keys = 1;\n\nINSERT INTO \"__EFMigrationsHistory\" (\"MigrationId\", \"ProductVersion\")\nVALUES ('20240805122422_1.3.0-UpdateIdentityStructure', '9.0.4');\n\nBEGIN TRANSACTION;\nCREATE TABLE \"ef_temp_Credentials\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_Credentials\" PRIMARY KEY,\n \"AliasId\" TEXT NOT NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"Notes\" TEXT NULL,\n \"ServiceId\" TEXT NOT NULL,\n \"UpdatedAt\" TEXT NOT NULL,\n \"Username\" TEXT NULL,\n CONSTRAINT \"FK_Credentials_Aliases_AliasId\" FOREIGN KEY (\"AliasId\") REFERENCES \"Aliases\" (\"Id\") ON DELETE CASCADE,\n CONSTRAINT \"FK_Credentials_Services_ServiceId\" FOREIGN KEY (\"ServiceId\") REFERENCES \"Services\" (\"Id\") ON DELETE CASCADE\n);\n\nINSERT INTO \"ef_temp_Credentials\" (\"Id\", \"AliasId\", \"CreatedAt\", \"Notes\", \"ServiceId\", \"UpdatedAt\", \"Username\")\nSELECT \"Id\", \"AliasId\", \"CreatedAt\", \"Notes\", \"ServiceId\", \"UpdatedAt\", \"Username\"\nFROM \"Credentials\";\n\nCOMMIT;\n\nPRAGMA foreign_keys = 0;\n\nBEGIN TRANSACTION;\nDROP TABLE \"Credentials\";\n\nALTER TABLE \"ef_temp_Credentials\" RENAME TO \"Credentials\";\n\nCOMMIT;\n\nPRAGMA foreign_keys = 1;\n\nBEGIN TRANSACTION;\nCREATE INDEX \"IX_Credentials_AliasId\" ON \"Credentials\" (\"AliasId\");\n\nCREATE INDEX \"IX_Credentials_ServiceId\" ON \"Credentials\" (\"ServiceId\");\n\nCOMMIT;\n\nINSERT INTO \"__EFMigrationsHistory\" (\"MigrationId\", \"ProductVersion\")\nVALUES ('20240812141727_1.3.1-MakeUsernameOptional', '9.0.4');\n\nBEGIN TRANSACTION;\nALTER TABLE \"Settings\" ADD \"IsDeleted\" INTEGER NOT NULL DEFAULT 0;\n\nALTER TABLE \"Services\" ADD \"IsDeleted\" INTEGER NOT NULL DEFAULT 0;\n\nALTER TABLE \"Passwords\" ADD \"IsDeleted\" INTEGER NOT NULL DEFAULT 0;\n\nALTER TABLE \"EncryptionKeys\" ADD \"IsDeleted\" INTEGER NOT NULL DEFAULT 0;\n\nALTER TABLE \"Credentials\" ADD \"IsDeleted\" INTEGER NOT NULL DEFAULT 0;\n\nALTER TABLE \"Attachment\" ADD \"IsDeleted\" INTEGER NOT NULL DEFAULT 0;\n\nALTER TABLE \"Aliases\" ADD \"IsDeleted\" INTEGER NOT NULL DEFAULT 0;\n\nINSERT INTO \"__EFMigrationsHistory\" (\"MigrationId\", \"ProductVersion\")\nVALUES ('20240916105320_1.4.0-AddSyncSupport', '9.0.4');\n\nALTER TABLE \"Attachment\" RENAME TO \"Attachments\";\n\nCREATE TABLE \"ef_temp_Attachments\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_Attachments\" PRIMARY KEY,\n \"Blob\" BLOB NOT NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"CredentialId\" TEXT NOT NULL,\n \"Filename\" TEXT NOT NULL,\n \"IsDeleted\" INTEGER NOT NULL,\n \"UpdatedAt\" TEXT NOT NULL,\n CONSTRAINT \"FK_Attachments_Credentials_CredentialId\" FOREIGN KEY (\"CredentialId\") REFERENCES \"Credentials\" (\"Id\") ON DELETE CASCADE\n);\n\nINSERT INTO \"ef_temp_Attachments\" (\"Id\", \"Blob\", \"CreatedAt\", \"CredentialId\", \"Filename\", \"IsDeleted\", \"UpdatedAt\")\nSELECT \"Id\", \"Blob\", \"CreatedAt\", \"CredentialId\", \"Filename\", \"IsDeleted\", \"UpdatedAt\"\nFROM \"Attachments\";\n\nCOMMIT;\n\nPRAGMA foreign_keys = 0;\n\nBEGIN TRANSACTION;\nDROP TABLE \"Attachments\";\n\nALTER TABLE \"ef_temp_Attachments\" RENAME TO \"Attachments\";\n\nCOMMIT;\n\nPRAGMA foreign_keys = 1;\n\nBEGIN TRANSACTION;\nCREATE INDEX \"IX_Attachments_CredentialId\" ON \"Attachments\" (\"CredentialId\");\n\nCOMMIT;\n\nINSERT INTO \"__EFMigrationsHistory\" (\"MigrationId\", \"ProductVersion\")\nVALUES ('20240917191243_1.4.1-RenameAttachmentsPlural', '9.0.4');\n\nBEGIN TRANSACTION;\nCREATE TABLE \"TotpCodes\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_TotpCodes\" PRIMARY KEY,\n \"Name\" TEXT NOT NULL,\n \"SecretKey\" TEXT NOT NULL,\n \"CredentialId\" TEXT NOT NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"UpdatedAt\" TEXT NOT NULL,\n \"IsDeleted\" INTEGER NOT NULL,\n CONSTRAINT \"FK_TotpCodes_Credentials_CredentialId\" FOREIGN KEY (\"CredentialId\") REFERENCES \"Credentials\" (\"Id\") ON DELETE CASCADE\n);\n\nCREATE INDEX \"IX_TotpCodes_CredentialId\" ON \"TotpCodes\" (\"CredentialId\");\n\nINSERT INTO \"__EFMigrationsHistory\" (\"MigrationId\", \"ProductVersion\")\nVALUES ('20250310131554_1.5.0-AddTotpCodes', '9.0.4');\n\n\nPRAGMA foreign_keys = OFF;\n\n-- Clean up any existing temp tables first\nDROP TABLE IF EXISTS \"__EFMigrationsHistory_temp\";\nDROP TABLE IF EXISTS \"Aliases_temp\";\nDROP TABLE IF EXISTS \"Services_temp\";\nDROP TABLE IF EXISTS \"EncryptionKeys_temp\";\nDROP TABLE IF EXISTS \"Settings_temp\";\nDROP TABLE IF EXISTS \"Credentials_temp\";\nDROP TABLE IF EXISTS \"Attachments_temp\";\nDROP TABLE IF EXISTS \"Passwords_temp\";\nDROP TABLE IF EXISTS \"TotpCodes_temp\";\n\n-- Create backup tables for all data\nCREATE TABLE \"__EFMigrationsHistory_temp\" AS SELECT * FROM \"__EFMigrationsHistory\";\nCREATE TABLE \"Aliases_temp\" AS SELECT * FROM \"Aliases\";\nCREATE TABLE \"Services_temp\" AS SELECT * FROM \"Services\";\nCREATE TABLE \"EncryptionKeys_temp\" AS SELECT * FROM \"EncryptionKeys\";\nCREATE TABLE \"Settings_temp\" AS SELECT * FROM \"Settings\";\nCREATE TABLE \"Credentials_temp\" AS SELECT * FROM \"Credentials\";\nCREATE TABLE \"Attachments_temp\" AS SELECT * FROM \"Attachments\";\nCREATE TABLE \"Passwords_temp\" AS SELECT * FROM \"Passwords\";\nCREATE TABLE \"TotpCodes_temp\" AS SELECT * FROM \"TotpCodes\";\n\n-- Delete orphaned records that do not have a valid FK to the credential object\nDELETE FROM \"Attachments_temp\" WHERE \"CredentialId\" NOT IN (SELECT \"Id\" FROM \"Credentials_temp\");\nDELETE FROM \"Passwords_temp\" WHERE \"CredentialId\" NOT IN (SELECT \"Id\" FROM \"Credentials_temp\");\nDELETE FROM \"TotpCodes_temp\" WHERE \"CredentialId\" NOT IN (SELECT \"Id\" FROM \"Credentials_temp\");\n\n-- Delete orphaned credentials that do not have valid FKs to alias or service objects\nDELETE FROM \"Credentials_temp\" WHERE \"AliasId\" NOT IN (SELECT \"Id\" FROM \"Aliases_temp\");\nDELETE FROM \"Credentials_temp\" WHERE \"ServiceId\" NOT IN (SELECT \"Id\" FROM \"Services_temp\");\n\n-- After cleaning credentials, clean dependent tables again in case we removed credentials\nDELETE FROM \"Attachments_temp\" WHERE \"CredentialId\" NOT IN (SELECT \"Id\" FROM \"Credentials_temp\");\nDELETE FROM \"Passwords_temp\" WHERE \"CredentialId\" NOT IN (SELECT \"Id\" FROM \"Credentials_temp\");\nDELETE FROM \"TotpCodes_temp\" WHERE \"CredentialId\" NOT IN (SELECT \"Id\" FROM \"Credentials_temp\");\n\n-- Drop all existing tables\nDROP TABLE \"TotpCodes\";\nDROP TABLE \"Passwords\";\nDROP TABLE \"Attachments\";\nDROP TABLE \"Credentials\";\nDROP TABLE \"Settings\";\nDROP TABLE \"EncryptionKeys\";\nDROP TABLE \"Services\";\nDROP TABLE \"Aliases\";\nDROP TABLE \"__EFMigrationsHistory\";\n\n-- Recreate tables with proper constraints (no dependencies first)\nCREATE TABLE \"__EFMigrationsHistory\" (\n \"MigrationId\" TEXT NOT NULL CONSTRAINT \"PK___EFMigrationsHistory\" PRIMARY KEY,\n \"ProductVersion\" TEXT NOT NULL\n);\n\nCREATE TABLE \"Aliases\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_Aliases\" PRIMARY KEY,\n \"BirthDate\" TEXT NOT NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"Email\" TEXT NULL,\n \"FirstName\" VARCHAR NULL,\n \"Gender\" VARCHAR NULL,\n \"LastName\" VARCHAR NULL,\n \"NickName\" VARCHAR NULL,\n \"UpdatedAt\" TEXT NOT NULL,\n \"IsDeleted\" INTEGER NOT NULL DEFAULT 0\n);\n\nCREATE TABLE \"Services\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_Services\" PRIMARY KEY,\n \"Name\" TEXT NULL,\n \"Url\" TEXT NULL,\n \"Logo\" BLOB NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"UpdatedAt\" TEXT NOT NULL,\n \"IsDeleted\" INTEGER NOT NULL DEFAULT 0\n);\n\nCREATE TABLE \"EncryptionKeys\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_EncryptionKeys\" PRIMARY KEY,\n \"PublicKey\" TEXT NOT NULL,\n \"PrivateKey\" TEXT NOT NULL,\n \"IsPrimary\" INTEGER NOT NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"UpdatedAt\" TEXT NOT NULL,\n \"IsDeleted\" INTEGER NOT NULL DEFAULT 0\n);\n\nCREATE TABLE \"Settings\" (\n \"Key\" TEXT NOT NULL CONSTRAINT \"PK_Settings\" PRIMARY KEY,\n \"Value\" TEXT NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"UpdatedAt\" TEXT NOT NULL,\n \"IsDeleted\" INTEGER NOT NULL DEFAULT 0\n);\n\n-- Tables with foreign keys\nCREATE TABLE \"Credentials\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_Credentials\" PRIMARY KEY,\n \"AliasId\" TEXT NOT NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"Notes\" TEXT NULL,\n \"ServiceId\" TEXT NOT NULL,\n \"UpdatedAt\" TEXT NOT NULL,\n \"Username\" TEXT NULL,\n \"IsDeleted\" INTEGER NOT NULL DEFAULT 0,\n CONSTRAINT \"FK_Credentials_Aliases_AliasId\" FOREIGN KEY (\"AliasId\") REFERENCES \"Aliases\" (\"Id\") ON DELETE CASCADE,\n CONSTRAINT \"FK_Credentials_Services_ServiceId\" FOREIGN KEY (\"ServiceId\") REFERENCES \"Services\" (\"Id\") ON DELETE CASCADE\n);\n\nCREATE TABLE \"Attachments\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_Attachments\" PRIMARY KEY,\n \"Blob\" BLOB NOT NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"CredentialId\" TEXT NOT NULL,\n \"Filename\" TEXT NOT NULL,\n \"IsDeleted\" INTEGER NOT NULL DEFAULT 0,\n \"UpdatedAt\" TEXT NOT NULL,\n CONSTRAINT \"FK_Attachments_Credentials_CredentialId\" FOREIGN KEY (\"CredentialId\") REFERENCES \"Credentials\" (\"Id\") ON DELETE CASCADE\n);\n\nCREATE TABLE \"Passwords\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_Passwords\" PRIMARY KEY,\n \"Value\" TEXT NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"UpdatedAt\" TEXT NOT NULL,\n \"CredentialId\" TEXT NOT NULL,\n \"IsDeleted\" INTEGER NOT NULL DEFAULT 0,\n CONSTRAINT \"FK_Passwords_Credentials_CredentialId\" FOREIGN KEY (\"CredentialId\") REFERENCES \"Credentials\" (\"Id\") ON DELETE CASCADE\n);\n\nCREATE TABLE \"TotpCodes\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_TotpCodes\" PRIMARY KEY,\n \"Name\" TEXT NOT NULL,\n \"SecretKey\" TEXT NOT NULL,\n \"CredentialId\" TEXT NOT NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"UpdatedAt\" TEXT NOT NULL,\n \"IsDeleted\" INTEGER NOT NULL DEFAULT 0,\n CONSTRAINT \"FK_TotpCodes_Credentials_CredentialId\" FOREIGN KEY (\"CredentialId\") REFERENCES \"Credentials\" (\"Id\") ON DELETE CASCADE\n);\n\n\n-- Restore data from temp tables\nINSERT INTO \"__EFMigrationsHistory\" SELECT * FROM \"__EFMigrationsHistory_temp\";\nINSERT INTO \"Aliases\" SELECT * FROM \"Aliases_temp\";\nINSERT INTO \"Services\" SELECT * FROM \"Services_temp\";\nINSERT INTO \"EncryptionKeys\" SELECT * FROM \"EncryptionKeys_temp\";\nINSERT INTO \"Settings\" SELECT * FROM \"Settings_temp\";\nINSERT INTO \"Credentials\" SELECT * FROM \"Credentials_temp\";\nINSERT INTO \"Attachments\" SELECT * FROM \"Attachments_temp\";\nINSERT INTO \"Passwords\" SELECT * FROM \"Passwords_temp\";\nINSERT INTO \"TotpCodes\" SELECT * FROM \"TotpCodes_temp\";\n\n-- =====================================================================================\n-- Date Format Normalization Migration\n-- =====================================================================================\n-- This migration normalizes ALL date fields to the standard format: 'yyyy-MM-dd HH:mm:ss.fff'\n-- Previously the different clients used different date formats which complicate date parsing.\n-- From version 0.24.0 onwards, all new dates are stored in this standard format.\n\n-- Update Aliases table (CreatedAt, UpdatedAt, BirthDate)\nUPDATE \"Aliases\" SET \"CreatedAt\" =\n CASE\n -- Already in correct format (yyyy-MM-dd HH:mm:ss.fff) - no change\n WHEN \"CreatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9] [0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9][0-9][0-9]'\n THEN \"CreatedAt\"\n\n -- ISO 8601 with milliseconds (yyyy-MM-ddTHH:mm:ss.fffZ) -> Replace T with space, remove Z and everything after .fff\n WHEN \"CreatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]T[0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9]*'\n THEN substr(\"CreatedAt\", 1, 10) || ' ' || substr(\"CreatedAt\", 12, 12)\n\n -- Without milliseconds (yyyy-MM-dd HH:mm:ss or yyyy-MM-ddTHH:mm:ssZ) -> Add .000\n WHEN \"CreatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9][T ][0-9][0-9]:[0-9][0-9]:[0-9][0-9]*'\n THEN substr(\"CreatedAt\", 1, 10) || ' ' || substr(replace(\"CreatedAt\", 'T', ' '), 12, 8) || '.000'\n\n -- Fallback: if none match, keep as-is (edge case)\n ELSE \"CreatedAt\"\n END;\n\nUPDATE \"Aliases\" SET \"UpdatedAt\" =\n CASE\n WHEN \"UpdatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9] [0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9][0-9][0-9]'\n THEN \"UpdatedAt\"\n WHEN \"UpdatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]T[0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9]*'\n THEN substr(\"UpdatedAt\", 1, 10) || ' ' || substr(\"UpdatedAt\", 12, 12)\n WHEN \"UpdatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9][T ][0-9][0-9]:[0-9][0-9]:[0-9][0-9]*'\n THEN substr(\"UpdatedAt\", 1, 10) || ' ' || substr(replace(\"UpdatedAt\", 'T', ' '), 12, 8) || '.000'\n ELSE \"UpdatedAt\"\n END;\n\n-- BirthDate: Always set time to 00:00:00 (no milliseconds for birth dates)\nUPDATE \"Aliases\" SET \"BirthDate\" =\n CASE\n -- If empty or already '0001-01-01 00:00:00', keep as-is\n WHEN \"BirthDate\" = '' OR \"BirthDate\" = '0001-01-01 00:00:00'\n THEN \"BirthDate\"\n\n -- If already in correct format (yyyy-MM-dd 00:00:00), keep as-is\n WHEN \"BirthDate\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9] 00:00:00'\n THEN \"BirthDate\"\n\n -- Extract date part and set time to 00:00:00\n WHEN \"BirthDate\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]*'\n THEN substr(\"BirthDate\", 1, 10) || ' 00:00:00'\n\n -- Fallback\n ELSE \"BirthDate\"\n END;\n\n-- Update Services table (CreatedAt, UpdatedAt)\nUPDATE \"Services\" SET \"CreatedAt\" =\n CASE\n WHEN \"CreatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9] [0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9][0-9][0-9]'\n THEN \"CreatedAt\"\n WHEN \"CreatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]T[0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9]*'\n THEN substr(\"CreatedAt\", 1, 10) || ' ' || substr(\"CreatedAt\", 12, 12)\n WHEN \"CreatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9][T ][0-9][0-9]:[0-9][0-9]:[0-9][0-9]*'\n THEN substr(\"CreatedAt\", 1, 10) || ' ' || substr(replace(\"CreatedAt\", 'T', ' '), 12, 8) || '.000'\n ELSE \"CreatedAt\"\n END;\n\nUPDATE \"Services\" SET \"UpdatedAt\" =\n CASE\n WHEN \"UpdatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9] [0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9][0-9][0-9]'\n THEN \"UpdatedAt\"\n WHEN \"UpdatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]T[0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9]*'\n THEN substr(\"UpdatedAt\", 1, 10) || ' ' || substr(\"UpdatedAt\", 12, 12)\n WHEN \"UpdatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9][T ][0-9][0-9]:[0-9][0-9]:[0-9][0-9]*'\n THEN substr(\"UpdatedAt\", 1, 10) || ' ' || substr(replace(\"UpdatedAt\", 'T', ' '), 12, 8) || '.000'\n ELSE \"UpdatedAt\"\n END;\n\n-- Update EncryptionKeys table (CreatedAt, UpdatedAt)\nUPDATE \"EncryptionKeys\" SET \"CreatedAt\" =\n CASE\n WHEN \"CreatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9] [0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9][0-9][0-9]'\n THEN \"CreatedAt\"\n WHEN \"CreatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]T[0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9]*'\n THEN substr(\"CreatedAt\", 1, 10) || ' ' || substr(\"CreatedAt\", 12, 12)\n WHEN \"CreatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9][T ][0-9][0-9]:[0-9][0-9]:[0-9][0-9]*'\n THEN substr(\"CreatedAt\", 1, 10) || ' ' || substr(replace(\"CreatedAt\", 'T', ' '), 12, 8) || '.000'\n ELSE \"CreatedAt\"\n END;\n\nUPDATE \"EncryptionKeys\" SET \"UpdatedAt\" =\n CASE\n WHEN \"UpdatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9] [0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9][0-9][0-9]'\n THEN \"UpdatedAt\"\n WHEN \"UpdatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]T[0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9]*'\n THEN substr(\"UpdatedAt\", 1, 10) || ' ' || substr(\"UpdatedAt\", 12, 12)\n WHEN \"UpdatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9][T ][0-9][0-9]:[0-9][0-9]:[0-9][0-9]*'\n THEN substr(\"UpdatedAt\", 1, 10) || ' ' || substr(replace(\"UpdatedAt\", 'T', ' '), 12, 8) || '.000'\n ELSE \"UpdatedAt\"\n END;\n\n-- Update Settings table (CreatedAt, UpdatedAt)\nUPDATE \"Settings\" SET \"CreatedAt\" =\n CASE\n WHEN \"CreatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9] [0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9][0-9][0-9]'\n THEN \"CreatedAt\"\n WHEN \"CreatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]T[0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9]*'\n THEN substr(\"CreatedAt\", 1, 10) || ' ' || substr(\"CreatedAt\", 12, 12)\n WHEN \"CreatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9][T ][0-9][0-9]:[0-9][0-9]:[0-9][0-9]*'\n THEN substr(\"CreatedAt\", 1, 10) || ' ' || substr(replace(\"CreatedAt\", 'T', ' '), 12, 8) || '.000'\n ELSE \"CreatedAt\"\n END;\n\nUPDATE \"Settings\" SET \"UpdatedAt\" =\n CASE\n WHEN \"UpdatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9] [0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9][0-9][0-9]'\n THEN \"UpdatedAt\"\n WHEN \"UpdatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]T[0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9]*'\n THEN substr(\"UpdatedAt\", 1, 10) || ' ' || substr(\"UpdatedAt\", 12, 12)\n WHEN \"UpdatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9][T ][0-9][0-9]:[0-9][0-9]:[0-9][0-9]*'\n THEN substr(\"UpdatedAt\", 1, 10) || ' ' || substr(replace(\"UpdatedAt\", 'T', ' '), 12, 8) || '.000'\n ELSE \"UpdatedAt\"\n END;\n\n-- Update Credentials table (CreatedAt, UpdatedAt)\nUPDATE \"Credentials\" SET \"CreatedAt\" =\n CASE\n WHEN \"CreatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9] [0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9][0-9][0-9]'\n THEN \"CreatedAt\"\n WHEN \"CreatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]T[0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9]*'\n THEN substr(\"CreatedAt\", 1, 10) || ' ' || substr(\"CreatedAt\", 12, 12)\n WHEN \"CreatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9][T ][0-9][0-9]:[0-9][0-9]:[0-9][0-9]*'\n THEN substr(\"CreatedAt\", 1, 10) || ' ' || substr(replace(\"CreatedAt\", 'T', ' '), 12, 8) || '.000'\n ELSE \"CreatedAt\"\n END;\n\nUPDATE \"Credentials\" SET \"UpdatedAt\" =\n CASE\n WHEN \"UpdatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9] [0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9][0-9][0-9]'\n THEN \"UpdatedAt\"\n WHEN \"UpdatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]T[0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9]*'\n THEN substr(\"UpdatedAt\", 1, 10) || ' ' || substr(\"UpdatedAt\", 12, 12)\n WHEN \"UpdatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9][T ][0-9][0-9]:[0-9][0-9]:[0-9][0-9]*'\n THEN substr(\"UpdatedAt\", 1, 10) || ' ' || substr(replace(\"UpdatedAt\", 'T', ' '), 12, 8) || '.000'\n ELSE \"UpdatedAt\"\n END;\n\n-- Update Attachments table (CreatedAt, UpdatedAt)\nUPDATE \"Attachments\" SET \"CreatedAt\" =\n CASE\n WHEN \"CreatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9] [0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9][0-9][0-9]'\n THEN \"CreatedAt\"\n WHEN \"CreatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]T[0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9]*'\n THEN substr(\"CreatedAt\", 1, 10) || ' ' || substr(\"CreatedAt\", 12, 12)\n WHEN \"CreatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9][T ][0-9][0-9]:[0-9][0-9]:[0-9][0-9]*'\n THEN substr(\"CreatedAt\", 1, 10) || ' ' || substr(replace(\"CreatedAt\", 'T', ' '), 12, 8) || '.000'\n ELSE \"CreatedAt\"\n END;\n\nUPDATE \"Attachments\" SET \"UpdatedAt\" =\n CASE\n WHEN \"UpdatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9] [0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9][0-9][0-9]'\n THEN \"UpdatedAt\"\n WHEN \"UpdatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]T[0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9]*'\n THEN substr(\"UpdatedAt\", 1, 10) || ' ' || substr(\"UpdatedAt\", 12, 12)\n WHEN \"UpdatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9][T ][0-9][0-9]:[0-9][0-9]:[0-9][0-9]*'\n THEN substr(\"UpdatedAt\", 1, 10) || ' ' || substr(replace(\"UpdatedAt\", 'T', ' '), 12, 8) || '.000'\n ELSE \"UpdatedAt\"\n END;\n\n-- Update Passwords table (CreatedAt, UpdatedAt)\nUPDATE \"Passwords\" SET \"CreatedAt\" =\n CASE\n WHEN \"CreatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9] [0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9][0-9][0-9]'\n THEN \"CreatedAt\"\n WHEN \"CreatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]T[0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9]*'\n THEN substr(\"CreatedAt\", 1, 10) || ' ' || substr(\"CreatedAt\", 12, 12)\n WHEN \"CreatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9][T ][0-9][0-9]:[0-9][0-9]:[0-9][0-9]*'\n THEN substr(\"CreatedAt\", 1, 10) || ' ' || substr(replace(\"CreatedAt\", 'T', ' '), 12, 8) || '.000'\n ELSE \"CreatedAt\"\n END;\n\nUPDATE \"Passwords\" SET \"UpdatedAt\" =\n CASE\n WHEN \"UpdatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9] [0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9][0-9][0-9]'\n THEN \"UpdatedAt\"\n WHEN \"UpdatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]T[0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9]*'\n THEN substr(\"UpdatedAt\", 1, 10) || ' ' || substr(\"UpdatedAt\", 12, 12)\n WHEN \"UpdatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9][T ][0-9][0-9]:[0-9][0-9]:[0-9][0-9]*'\n THEN substr(\"UpdatedAt\", 1, 10) || ' ' || substr(replace(\"UpdatedAt\", 'T', ' '), 12, 8) || '.000'\n ELSE \"UpdatedAt\"\n END;\n\n-- Update TotpCodes table (CreatedAt, UpdatedAt)\nUPDATE \"TotpCodes\" SET \"CreatedAt\" =\n CASE\n WHEN \"CreatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9] [0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9][0-9][0-9]'\n THEN \"CreatedAt\"\n WHEN \"CreatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]T[0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9]*'\n THEN substr(\"CreatedAt\", 1, 10) || ' ' || substr(\"CreatedAt\", 12, 12)\n WHEN \"CreatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9][T ][0-9][0-9]:[0-9][0-9]:[0-9][0-9]*'\n THEN substr(\"CreatedAt\", 1, 10) || ' ' || substr(replace(\"CreatedAt\", 'T', ' '), 12, 8) || '.000'\n ELSE \"CreatedAt\"\n END;\n\nUPDATE \"TotpCodes\" SET \"UpdatedAt\" =\n CASE\n WHEN \"UpdatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9] [0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9][0-9][0-9]'\n THEN \"UpdatedAt\"\n WHEN \"UpdatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]T[0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9]*'\n THEN substr(\"UpdatedAt\", 1, 10) || ' ' || substr(\"UpdatedAt\", 12, 12)\n WHEN \"UpdatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9][T ][0-9][0-9]:[0-9][0-9]:[0-9][0-9]*'\n THEN substr(\"UpdatedAt\", 1, 10) || ' ' || substr(replace(\"UpdatedAt\", 'T', ' '), 12, 8) || '.000'\n ELSE \"UpdatedAt\"\n END;\n\n-- =====================================================================================\n-- End of Date Format Normalization Migration\n-- =====================================================================================\n\n-- Recreate indexes\nCREATE INDEX \"IX_Credentials_AliasId\" ON \"Credentials\" (\"AliasId\");\nCREATE INDEX \"IX_Credentials_ServiceId\" ON \"Credentials\" (\"ServiceId\");\nCREATE INDEX \"IX_Attachments_CredentialId\" ON \"Attachments\" (\"CredentialId\");\nCREATE INDEX \"IX_Passwords_CredentialId\" ON \"Passwords\" (\"CredentialId\");\nCREATE INDEX \"IX_TotpCodes_CredentialId\" ON \"TotpCodes\" (\"CredentialId\");\n\n-- Clean up temp tables\nDROP TABLE \"__EFMigrationsHistory_temp\";\nDROP TABLE \"Aliases_temp\";\nDROP TABLE \"Services_temp\";\nDROP TABLE \"EncryptionKeys_temp\";\nDROP TABLE \"Settings_temp\";\nDROP TABLE \"Credentials_temp\";\nDROP TABLE \"Attachments_temp\";\nDROP TABLE \"Passwords_temp\";\nDROP TABLE \"TotpCodes_temp\";\n\nPRAGMA foreign_keys = ON;\n\n\nCREATE TABLE \"Passkeys\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_Passkeys\" PRIMARY KEY,\n \"RpId\" TEXT COLLATE NOCASE NOT NULL,\n \"UserHandle\" BLOB NOT NULL,\n \"PublicKey\" TEXT NOT NULL,\n \"PrivateKey\" TEXT NOT NULL,\n \"PrfKey\" BLOB NULL,\n \"DisplayName\" TEXT NOT NULL,\n \"AdditionalData\" BLOB NULL,\n \"CredentialId\" TEXT NOT NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"UpdatedAt\" TEXT NOT NULL,\n \"IsDeleted\" INTEGER NOT NULL,\n CONSTRAINT \"FK_Passkeys_Credentials_CredentialId\" FOREIGN KEY (\"CredentialId\") REFERENCES \"Credentials\" (\"Id\") ON DELETE CASCADE\n);\n\nCREATE INDEX \"IX_Passkeys_CredentialId\" ON \"Passkeys\" (\"CredentialId\");\n\nCREATE INDEX \"IX_Passkeys_RpId\" ON \"Passkeys\" (\"RpId\");\n\nINSERT INTO \"__EFMigrationsHistory\" (\"MigrationId\", \"ProductVersion\")\nVALUES ('20251014122838_1.6.0-AddPasskeys', '9.0.4');\n\nALTER TABLE \"TotpCodes\" RENAME COLUMN \"CredentialId\" TO \"ItemId\";\n\nDROP INDEX IF EXISTS \"IX_TotpCodes_CredentialId\";\n\nCREATE INDEX IF NOT EXISTS \"IX_TotpCodes_ItemId\" ON \"TotpCodes\" (\"ItemId\");\n\nALTER TABLE \"Passkeys\" RENAME COLUMN \"CredentialId\" TO \"ItemId\";\n\nDROP INDEX IF EXISTS \"IX_Passkeys_CredentialId\";\n\nCREATE INDEX IF NOT EXISTS \"IX_Passkeys_ItemId\" ON \"Passkeys\" (\"ItemId\");\n\nALTER TABLE \"Attachments\" RENAME COLUMN \"CredentialId\" TO \"ItemId\";\n\nDROP INDEX IF EXISTS \"IX_Attachments_CredentialId\";\n\nCREATE INDEX IF NOT EXISTS \"IX_Attachments_ItemId\" ON \"Attachments\" (\"ItemId\");\n\nCREATE TABLE \"FieldDefinitions\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_FieldDefinitions\" PRIMARY KEY,\n \"FieldType\" TEXT NOT NULL,\n \"Label\" TEXT NOT NULL,\n \"IsMultiValue\" INTEGER NOT NULL,\n \"IsHidden\" INTEGER NOT NULL,\n \"EnableHistory\" INTEGER NOT NULL,\n \"Weight\" INTEGER NOT NULL,\n \"ApplicableToTypes\" TEXT NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"UpdatedAt\" TEXT NOT NULL,\n \"IsDeleted\" INTEGER NOT NULL\n);\n\nCREATE TABLE \"Folders\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_Folders\" PRIMARY KEY,\n \"Name\" TEXT NOT NULL,\n \"ParentFolderId\" TEXT NULL,\n \"Weight\" INTEGER NOT NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"UpdatedAt\" TEXT NOT NULL,\n \"IsDeleted\" INTEGER NOT NULL,\n CONSTRAINT \"FK_Folders_Folders_ParentFolderId\" FOREIGN KEY (\"ParentFolderId\") REFERENCES \"Folders\" (\"Id\") ON DELETE CASCADE\n);\n\nCREATE TABLE \"Logos\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_Logos\" PRIMARY KEY,\n \"Source\" TEXT NOT NULL,\n \"FileData\" BLOB NULL,\n \"MimeType\" TEXT NULL,\n \"FetchedAt\" TEXT NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"UpdatedAt\" TEXT NOT NULL,\n \"IsDeleted\" INTEGER NOT NULL\n);\n\nCREATE TABLE \"Tags\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_Tags\" PRIMARY KEY,\n \"Name\" TEXT NOT NULL,\n \"Color\" TEXT NULL,\n \"DisplayOrder\" INTEGER NOT NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"UpdatedAt\" TEXT NOT NULL,\n \"IsDeleted\" INTEGER NOT NULL\n);\n\nCREATE TABLE \"Items\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_Items\" PRIMARY KEY,\n \"Name\" TEXT NULL,\n \"ItemType\" TEXT NOT NULL,\n \"LogoId\" TEXT NULL,\n \"DeletedAt\" TEXT NULL,\n \"FolderId\" TEXT NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"UpdatedAt\" TEXT NOT NULL,\n \"IsDeleted\" INTEGER NOT NULL,\n CONSTRAINT \"FK_Items_Folders_FolderId\" FOREIGN KEY (\"FolderId\") REFERENCES \"Folders\" (\"Id\") ON DELETE SET NULL,\n CONSTRAINT \"FK_Items_Logos_LogoId\" FOREIGN KEY (\"LogoId\") REFERENCES \"Logos\" (\"Id\") ON DELETE SET NULL\n);\n\nCREATE TABLE \"FieldHistories\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_FieldHistories\" PRIMARY KEY,\n \"ItemId\" TEXT NOT NULL,\n \"FieldDefinitionId\" TEXT NULL,\n \"FieldKey\" TEXT NULL,\n \"ValueSnapshot\" TEXT NOT NULL,\n \"ChangedAt\" TEXT NOT NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"UpdatedAt\" TEXT NOT NULL,\n \"IsDeleted\" INTEGER NOT NULL,\n CONSTRAINT \"FK_FieldHistories_FieldDefinitions_FieldDefinitionId\" FOREIGN KEY (\"FieldDefinitionId\") REFERENCES \"FieldDefinitions\" (\"Id\") ON DELETE CASCADE,\n CONSTRAINT \"FK_FieldHistories_Items_ItemId\" FOREIGN KEY (\"ItemId\") REFERENCES \"Items\" (\"Id\") ON DELETE CASCADE\n);\n\nCREATE TABLE \"FieldValues\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_FieldValues\" PRIMARY KEY,\n \"ItemId\" TEXT NOT NULL,\n \"FieldDefinitionId\" TEXT NULL,\n \"FieldKey\" TEXT NULL,\n \"Value\" TEXT NULL,\n \"Weight\" INTEGER NOT NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"UpdatedAt\" TEXT NOT NULL,\n \"IsDeleted\" INTEGER NOT NULL,\n CONSTRAINT \"FK_FieldValues_FieldDefinitions_FieldDefinitionId\" FOREIGN KEY (\"FieldDefinitionId\") REFERENCES \"FieldDefinitions\" (\"Id\") ON DELETE CASCADE,\n CONSTRAINT \"FK_FieldValues_Items_ItemId\" FOREIGN KEY (\"ItemId\") REFERENCES \"Items\" (\"Id\") ON DELETE CASCADE\n);\n\nCREATE TABLE \"ItemTags\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_ItemTags\" PRIMARY KEY,\n \"ItemId\" TEXT NOT NULL,\n \"TagId\" TEXT NOT NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"UpdatedAt\" TEXT NOT NULL,\n \"IsDeleted\" INTEGER NOT NULL,\n CONSTRAINT \"FK_ItemTags_Items_ItemId\" FOREIGN KEY (\"ItemId\") REFERENCES \"Items\" (\"Id\") ON DELETE CASCADE,\n CONSTRAINT \"FK_ItemTags_Tags_TagId\" FOREIGN KEY (\"TagId\") REFERENCES \"Tags\" (\"Id\") ON DELETE CASCADE\n);\n\nCREATE INDEX \"IX_FieldHistories_FieldDefinitionId\" ON \"FieldHistories\" (\"FieldDefinitionId\");\n\nCREATE INDEX \"IX_FieldHistories_ItemId\" ON \"FieldHistories\" (\"ItemId\");\n\nCREATE INDEX \"IX_FieldValues_FieldDefinitionId\" ON \"FieldValues\" (\"FieldDefinitionId\");\n\nCREATE INDEX \"IX_FieldValues_FieldKey\" ON \"FieldValues\" (\"FieldKey\");\n\nCREATE INDEX \"IX_FieldValues_ItemId\" ON \"FieldValues\" (\"ItemId\");\n\nCREATE INDEX \"IX_FieldValues_ItemId_FieldDefinitionId_Weight\" ON \"FieldValues\" (\"ItemId\", \"FieldDefinitionId\", \"Weight\");\n\nCREATE INDEX \"IX_FieldValues_ItemId_FieldKey\" ON \"FieldValues\" (\"ItemId\", \"FieldKey\");\n\nCREATE INDEX \"IX_Folders_ParentFolderId\" ON \"Folders\" (\"ParentFolderId\");\n\nCREATE INDEX \"IX_Items_FolderId\" ON \"Items\" (\"FolderId\");\n\nCREATE INDEX \"IX_Items_LogoId\" ON \"Items\" (\"LogoId\");\n\nCREATE INDEX \"IX_ItemTags_ItemId\" ON \"ItemTags\" (\"ItemId\");\n\nCREATE UNIQUE INDEX \"IX_ItemTags_ItemId_TagId\" ON \"ItemTags\" (\"ItemId\", \"TagId\");\n\nCREATE INDEX \"IX_ItemTags_TagId\" ON \"ItemTags\" (\"TagId\");\n\nCREATE UNIQUE INDEX \"IX_Logos_Source\" ON \"Logos\" (\"Source\");\n\nCREATE INDEX \"IX_Tags_Name\" ON \"Tags\" (\"Name\");\n\n\n INSERT INTO Items (Id, Name, ItemType, LogoId, FolderId, CreatedAt, UpdatedAt, IsDeleted)\n SELECT\n c.Id,\n s.Name AS Name,\n CASE\n WHEN a.Id IS NOT NULL AND (\n (a.FirstName IS NOT NULL AND a.FirstName != '') OR\n (a.LastName IS NOT NULL AND a.LastName != '') OR\n (a.Gender IS NOT NULL AND a.Gender != '') OR\n (a.BirthDate IS NOT NULL AND a.BirthDate != '' AND a.BirthDate NOT LIKE '0001-%')\n ) THEN 'Alias'\n ELSE 'Login'\n END AS ItemType,\n NULL AS LogoId,\n NULL AS FolderId,\n c.CreatedAt,\n c.UpdatedAt,\n c.IsDeleted\n FROM Credentials c\n LEFT JOIN Services s ON s.Id = c.ServiceId\n LEFT JOIN Aliases a ON a.Id = c.AliasId;\n \n\n\n INSERT INTO Logos (Id, Source, FileData, MimeType, FetchedAt, CreatedAt, UpdatedAt, IsDeleted)\n SELECT\n UPPER(SUBSTR(hex(randomblob(4)), 1, 8) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(6)), 1, 12)) AS Id,\n -- Extract and normalize hostname: remove protocol, path, lowercase, and www. prefix\n REPLACE(\n LOWER(\n SUBSTR(\n CASE\n WHEN s.Url LIKE 'https://%' THEN SUBSTR(s.Url, 9)\n WHEN s.Url LIKE 'http://%' THEN SUBSTR(s.Url, 8)\n ELSE s.Url\n END,\n 1,\n CASE\n WHEN INSTR(\n CASE\n WHEN s.Url LIKE 'https://%' THEN SUBSTR(s.Url, 9)\n WHEN s.Url LIKE 'http://%' THEN SUBSTR(s.Url, 8)\n ELSE s.Url\n END, '/') > 0\n THEN INSTR(\n CASE\n WHEN s.Url LIKE 'https://%' THEN SUBSTR(s.Url, 9)\n WHEN s.Url LIKE 'http://%' THEN SUBSTR(s.Url, 8)\n ELSE s.Url\n END, '/') - 1\n ELSE LENGTH(\n CASE\n WHEN s.Url LIKE 'https://%' THEN SUBSTR(s.Url, 9)\n WHEN s.Url LIKE 'http://%' THEN SUBSTR(s.Url, 8)\n ELSE s.Url\n END)\n END\n )\n ),\n 'www.', ''\n ) AS Source,\n s.Logo AS FileData,\n 'image/png' AS MimeType,\n NULL AS FetchedAt,\n MIN(s.CreatedAt) AS CreatedAt,\n MAX(s.UpdatedAt) AS UpdatedAt,\n 0 AS IsDeleted\n FROM Services s\n WHERE s.Logo IS NOT NULL AND s.Url IS NOT NULL AND s.Url != ''\n GROUP BY REPLACE(\n LOWER(\n SUBSTR(\n CASE\n WHEN s.Url LIKE 'https://%' THEN SUBSTR(s.Url, 9)\n WHEN s.Url LIKE 'http://%' THEN SUBSTR(s.Url, 8)\n ELSE s.Url\n END,\n 1,\n CASE\n WHEN INSTR(\n CASE\n WHEN s.Url LIKE 'https://%' THEN SUBSTR(s.Url, 9)\n WHEN s.Url LIKE 'http://%' THEN SUBSTR(s.Url, 8)\n ELSE s.Url\n END, '/') > 0\n THEN INSTR(\n CASE\n WHEN s.Url LIKE 'https://%' THEN SUBSTR(s.Url, 9)\n WHEN s.Url LIKE 'http://%' THEN SUBSTR(s.Url, 8)\n ELSE s.Url\n END, '/') - 1\n ELSE LENGTH(\n CASE\n WHEN s.Url LIKE 'https://%' THEN SUBSTR(s.Url, 9)\n WHEN s.Url LIKE 'http://%' THEN SUBSTR(s.Url, 8)\n ELSE s.Url\n END)\n END\n )\n ),\n 'www.', ''\n );\n \n\n\n UPDATE Items\n SET LogoId = (\n SELECT l.Id FROM Logos l\n INNER JOIN Services s ON REPLACE(\n LOWER(\n SUBSTR(\n CASE\n WHEN s.Url LIKE 'https://%' THEN SUBSTR(s.Url, 9)\n WHEN s.Url LIKE 'http://%' THEN SUBSTR(s.Url, 8)\n ELSE s.Url\n END,\n 1,\n CASE\n WHEN INSTR(\n CASE\n WHEN s.Url LIKE 'https://%' THEN SUBSTR(s.Url, 9)\n WHEN s.Url LIKE 'http://%' THEN SUBSTR(s.Url, 8)\n ELSE s.Url\n END, '/') > 0\n THEN INSTR(\n CASE\n WHEN s.Url LIKE 'https://%' THEN SUBSTR(s.Url, 9)\n WHEN s.Url LIKE 'http://%' THEN SUBSTR(s.Url, 8)\n ELSE s.Url\n END, '/') - 1\n ELSE LENGTH(\n CASE\n WHEN s.Url LIKE 'https://%' THEN SUBSTR(s.Url, 9)\n WHEN s.Url LIKE 'http://%' THEN SUBSTR(s.Url, 8)\n ELSE s.Url\n END)\n END\n )\n ),\n 'www.', ''\n ) = l.Source\n INNER JOIN Credentials c ON c.ServiceId = s.Id\n WHERE c.Id = Items.Id\n LIMIT 1\n )\n WHERE EXISTS (\n SELECT 1 FROM Credentials c\n INNER JOIN Services s ON s.Id = c.ServiceId\n WHERE c.Id = Items.Id AND s.Logo IS NOT NULL\n );\n \n\n\n INSERT INTO FieldValues (Id, ItemId, FieldDefinitionId, FieldKey, Value, Weight, CreatedAt, UpdatedAt, IsDeleted)\n SELECT\n UPPER(SUBSTR(hex(randomblob(4)), 1, 8) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(6)), 1, 12)) AS Id,\n c.Id AS ItemId,\n NULL AS FieldDefinitionId,\n 'login.url' AS FieldKey,\n s.Url AS Value,\n 0 AS Weight,\n s.UpdatedAt AS CreatedAt,\n s.UpdatedAt AS UpdatedAt,\n 0 AS IsDeleted\n FROM Credentials c\n INNER JOIN Services s ON s.Id = c.ServiceId\n WHERE s.Url IS NOT NULL AND s.Url != '';\n \n\n\n INSERT INTO FieldValues (Id, ItemId, FieldDefinitionId, FieldKey, Value, Weight, CreatedAt, UpdatedAt, IsDeleted)\n SELECT\n UPPER(SUBSTR(hex(randomblob(4)), 1, 8) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(6)), 1, 12)) AS Id,\n c.Id AS ItemId,\n NULL AS FieldDefinitionId,\n 'login.username' AS FieldKey,\n c.Username AS Value,\n 0 AS Weight,\n c.UpdatedAt AS CreatedAt,\n c.UpdatedAt AS UpdatedAt,\n 0 AS IsDeleted\n FROM Credentials c\n WHERE c.Username IS NOT NULL AND c.Username != '';\n \n\n\n INSERT INTO FieldValues (Id, ItemId, FieldDefinitionId, FieldKey, Value, Weight, CreatedAt, UpdatedAt, IsDeleted)\n SELECT\n UPPER(SUBSTR(hex(randomblob(4)), 1, 8) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(6)), 1, 12)) AS Id,\n c.Id AS ItemId,\n NULL AS FieldDefinitionId,\n 'login.notes' AS FieldKey,\n c.Notes AS Value,\n 0 AS Weight,\n c.UpdatedAt AS CreatedAt,\n c.UpdatedAt AS UpdatedAt,\n 0 AS IsDeleted\n FROM Credentials c\n WHERE c.Notes IS NOT NULL AND c.Notes != '';\n \n\n\n INSERT INTO FieldValues (Id, ItemId, FieldDefinitionId, FieldKey, Value, Weight, CreatedAt, UpdatedAt, IsDeleted)\n SELECT\n UPPER(SUBSTR(hex(randomblob(4)), 1, 8) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(6)), 1, 12)) AS Id,\n p.CredentialId AS ItemId,\n NULL AS FieldDefinitionId,\n 'login.password' AS FieldKey,\n p.Value AS Value,\n 0 AS Weight,\n p.UpdatedAt AS CreatedAt,\n p.UpdatedAt AS UpdatedAt,\n 0 AS IsDeleted\n FROM Passwords p\n INNER JOIN (\n SELECT CredentialId, MAX(UpdatedAt) AS MaxUpdated, MAX(Id) AS MaxId\n FROM Passwords\n WHERE IsDeleted = 0\n GROUP BY CredentialId\n ) pm ON p.CredentialId = pm.CredentialId AND p.UpdatedAt = pm.MaxUpdated AND p.Id = pm.MaxId\n WHERE p.IsDeleted = 0;\n \n\n\n INSERT INTO FieldValues (Id, ItemId, FieldDefinitionId, FieldKey, Value, Weight, CreatedAt, UpdatedAt, IsDeleted)\n SELECT\n UPPER(SUBSTR(hex(randomblob(4)), 1, 8) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(6)), 1, 12)) AS Id,\n c.Id AS ItemId,\n NULL AS FieldDefinitionId,\n 'login.email' AS FieldKey,\n a.Email AS Value,\n 0 AS Weight,\n a.UpdatedAt AS CreatedAt,\n a.UpdatedAt AS UpdatedAt,\n 0 AS IsDeleted\n FROM Credentials c\n INNER JOIN Aliases a ON a.Id = c.AliasId\n WHERE a.Email IS NOT NULL AND a.Email != '';\n \n\n\n INSERT INTO FieldValues (Id, ItemId, FieldDefinitionId, FieldKey, Value, Weight, CreatedAt, UpdatedAt, IsDeleted)\n SELECT\n UPPER(SUBSTR(hex(randomblob(4)), 1, 8) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(6)), 1, 12)) AS Id,\n c.Id AS ItemId,\n NULL AS FieldDefinitionId,\n 'alias.first_name' AS FieldKey,\n a.FirstName AS Value,\n 0 AS Weight,\n a.UpdatedAt AS CreatedAt,\n a.UpdatedAt AS UpdatedAt,\n 0 AS IsDeleted\n FROM Credentials c\n INNER JOIN Aliases a ON a.Id = c.AliasId\n WHERE a.FirstName IS NOT NULL AND a.FirstName != '';\n \n\n\n INSERT INTO FieldValues (Id, ItemId, FieldDefinitionId, FieldKey, Value, Weight, CreatedAt, UpdatedAt, IsDeleted)\n SELECT\n UPPER(SUBSTR(hex(randomblob(4)), 1, 8) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(6)), 1, 12)) AS Id,\n c.Id AS ItemId,\n NULL AS FieldDefinitionId,\n 'alias.last_name' AS FieldKey,\n a.LastName AS Value,\n 0 AS Weight,\n a.UpdatedAt AS CreatedAt,\n a.UpdatedAt AS UpdatedAt,\n 0 AS IsDeleted\n FROM Credentials c\n INNER JOIN Aliases a ON a.Id = c.AliasId\n WHERE a.LastName IS NOT NULL AND a.LastName != '';\n \n\n\n INSERT INTO FieldValues (Id, ItemId, FieldDefinitionId, FieldKey, Value, Weight, CreatedAt, UpdatedAt, IsDeleted)\n SELECT\n UPPER(SUBSTR(hex(randomblob(4)), 1, 8) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(6)), 1, 12)) AS Id,\n c.Id AS ItemId,\n NULL AS FieldDefinitionId,\n 'alias.gender' AS FieldKey,\n a.Gender AS Value,\n 0 AS Weight,\n a.UpdatedAt AS CreatedAt,\n a.UpdatedAt AS UpdatedAt,\n 0 AS IsDeleted\n FROM Credentials c\n INNER JOIN Aliases a ON a.Id = c.AliasId\n WHERE a.Gender IS NOT NULL AND a.Gender != '';\n \n\n\n INSERT INTO FieldValues (Id, ItemId, FieldDefinitionId, FieldKey, Value, Weight, CreatedAt, UpdatedAt, IsDeleted)\n SELECT\n UPPER(SUBSTR(hex(randomblob(4)), 1, 8) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(6)), 1, 12)) AS Id,\n c.Id AS ItemId,\n NULL AS FieldDefinitionId,\n 'alias.birthdate' AS FieldKey,\n SUBSTR(a.BirthDate, 1, 10) AS Value,\n 0 AS Weight,\n a.UpdatedAt AS CreatedAt,\n a.UpdatedAt AS UpdatedAt,\n 0 AS IsDeleted\n FROM Credentials c\n INNER JOIN Aliases a ON a.Id = c.AliasId\n WHERE a.BirthDate IS NOT NULL AND a.BirthDate != '' AND a.BirthDate NOT LIKE '0001-%';\n \n\nDROP TABLE \"Passwords\";\n\nDROP TABLE \"Credentials\";\n\nDROP TABLE \"Aliases\";\n\nDROP TABLE \"Services\";\n\nCREATE TABLE \"ef_temp_Attachments\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_Attachments\" PRIMARY KEY,\n \"Blob\" BLOB NOT NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"Filename\" TEXT NOT NULL,\n \"IsDeleted\" INTEGER NOT NULL,\n \"ItemId\" TEXT NOT NULL,\n \"UpdatedAt\" TEXT NOT NULL,\n CONSTRAINT \"FK_Attachments_Items_ItemId\" FOREIGN KEY (\"ItemId\") REFERENCES \"Items\" (\"Id\") ON DELETE CASCADE\n);\n\nINSERT INTO \"ef_temp_Attachments\" (\"Id\", \"Blob\", \"CreatedAt\", \"Filename\", \"IsDeleted\", \"ItemId\", \"UpdatedAt\")\nSELECT \"Id\", \"Blob\", \"CreatedAt\", \"Filename\", \"IsDeleted\", \"ItemId\", \"UpdatedAt\"\nFROM \"Attachments\";\n\nCREATE TABLE \"ef_temp_Passkeys\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_Passkeys\" PRIMARY KEY,\n \"AdditionalData\" BLOB NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"DisplayName\" TEXT NOT NULL,\n \"IsDeleted\" INTEGER NOT NULL,\n \"ItemId\" TEXT NOT NULL,\n \"PrfKey\" BLOB NULL,\n \"PrivateKey\" TEXT NOT NULL,\n \"PublicKey\" TEXT NOT NULL,\n \"RpId\" TEXT COLLATE NOCASE NOT NULL,\n \"UpdatedAt\" TEXT NOT NULL,\n \"UserHandle\" BLOB NOT NULL,\n CONSTRAINT \"FK_Passkeys_Items_ItemId\" FOREIGN KEY (\"ItemId\") REFERENCES \"Items\" (\"Id\") ON DELETE CASCADE\n);\n\nINSERT INTO \"ef_temp_Passkeys\" (\"Id\", \"AdditionalData\", \"CreatedAt\", \"DisplayName\", \"IsDeleted\", \"ItemId\", \"PrfKey\", \"PrivateKey\", \"PublicKey\", \"RpId\", \"UpdatedAt\", \"UserHandle\")\nSELECT \"Id\", \"AdditionalData\", \"CreatedAt\", \"DisplayName\", \"IsDeleted\", \"ItemId\", \"PrfKey\", \"PrivateKey\", \"PublicKey\", \"RpId\", \"UpdatedAt\", \"UserHandle\"\nFROM \"Passkeys\";\n\nCREATE TABLE \"ef_temp_TotpCodes\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_TotpCodes\" PRIMARY KEY,\n \"CreatedAt\" TEXT NOT NULL,\n \"IsDeleted\" INTEGER NOT NULL,\n \"ItemId\" TEXT NOT NULL,\n \"Name\" TEXT NOT NULL,\n \"SecretKey\" TEXT NOT NULL,\n \"UpdatedAt\" TEXT NOT NULL,\n CONSTRAINT \"FK_TotpCodes_Items_ItemId\" FOREIGN KEY (\"ItemId\") REFERENCES \"Items\" (\"Id\") ON DELETE CASCADE\n);\n\nINSERT INTO \"ef_temp_TotpCodes\" (\"Id\", \"CreatedAt\", \"IsDeleted\", \"ItemId\", \"Name\", \"SecretKey\", \"UpdatedAt\")\nSELECT \"Id\", \"CreatedAt\", \"IsDeleted\", \"ItemId\", \"Name\", \"SecretKey\", \"UpdatedAt\"\nFROM \"TotpCodes\";\n\nCOMMIT;\n\nPRAGMA foreign_keys = 0;\n\nBEGIN TRANSACTION;\nDROP TABLE \"Attachments\";\n\nALTER TABLE \"ef_temp_Attachments\" RENAME TO \"Attachments\";\n\nDROP TABLE \"Passkeys\";\n\nALTER TABLE \"ef_temp_Passkeys\" RENAME TO \"Passkeys\";\n\nDROP TABLE \"TotpCodes\";\n\nALTER TABLE \"ef_temp_TotpCodes\" RENAME TO \"TotpCodes\";\n\nCOMMIT;\n\nPRAGMA foreign_keys = 1;\n\nBEGIN TRANSACTION;\nCREATE INDEX \"IX_Attachments_ItemId\" ON \"Attachments\" (\"ItemId\");\n\nCREATE INDEX \"IX_Passkeys_ItemId\" ON \"Passkeys\" (\"ItemId\");\n\nCREATE INDEX \"IX_Passkeys_RpId\" ON \"Passkeys\" (\"RpId\");\n\nCREATE INDEX \"IX_TotpCodes_ItemId\" ON \"TotpCodes\" (\"ItemId\");\n\nCOMMIT;\n\nINSERT INTO \"__EFMigrationsHistory\" (\"MigrationId\", \"ProductVersion\")\nVALUES ('20251213111207_1.7.0-FieldBasedDataModelUpdate', '9.0.4');\n\nBEGIN TRANSACTION;\nINSERT INTO \"__EFMigrationsHistory\" (\"MigrationId\", \"ProductVersion\")\nVALUES ('20260130221620_2.0.0-MajorVersionBump', '9.0.4');\n\nCOMMIT;\n"; /** * Individual migration SQL scripts * Auto-generated from EF Core migrations diff --git a/apps/browser-extension/src/utils/dist/core/vault/index.js b/apps/browser-extension/src/utils/dist/core/vault/index.js index e0802c5be..b8ea571cb 100644 --- a/apps/browser-extension/src/utils/dist/core/vault/index.js +++ b/apps/browser-extension/src/utils/dist/core/vault/index.js @@ -1296,6 +1296,12 @@ COMMIT; INSERT INTO "__EFMigrationsHistory" ("MigrationId", "ProductVersion") VALUES ('20251213111207_1.7.0-FieldBasedDataModelUpdate', '9.0.4'); + +BEGIN TRANSACTION; +INSERT INTO "__EFMigrationsHistory" ("MigrationId", "ProductVersion") +VALUES ('20260130221620_2.0.0-MajorVersionBump', '9.0.4'); + +COMMIT; `; var MIGRATION_SCRIPTS = { 1: `\uFEFFBEGIN TRANSACTION; @@ -2492,7 +2498,12 @@ CREATE INDEX "IX_TotpCodes_ItemId" ON "TotpCodes" ("ItemId"); COMMIT; INSERT INTO "__EFMigrationsHistory" ("MigrationId", "ProductVersion") -VALUES ('20251213111207_1.7.0-FieldBasedDataModelUpdate', '9.0.4');` +VALUES ('20251213111207_1.7.0-FieldBasedDataModelUpdate', '9.0.4');`, + 12: `\uFEFFBEGIN TRANSACTION; +INSERT INTO "__EFMigrationsHistory" ("MigrationId", "ProductVersion") +VALUES ('20260130221620_2.0.0-MajorVersionBump', '9.0.4'); + +COMMIT;` }; // src/sql/VaultVersions.ts @@ -2579,7 +2590,14 @@ var VAULT_VERSIONS = [ version: "1.7.0", description: "Update to Field-Based Data Model", releaseVersion: "0.26.0", - compatibleUpToVersion: "0.26.0" + compatibleUpToVersion: "0.25.0" + }, + { + revision: 13, + version: "2.0.0", + description: "Update to Field-Based Data Model", + releaseVersion: "0.26.1", + compatibleUpToVersion: "0.25.0" } ]; diff --git a/apps/browser-extension/src/utils/dist/core/vault/index.mjs b/apps/browser-extension/src/utils/dist/core/vault/index.mjs index 8c4d5fa37..d5e02f646 100644 --- a/apps/browser-extension/src/utils/dist/core/vault/index.mjs +++ b/apps/browser-extension/src/utils/dist/core/vault/index.mjs @@ -1264,6 +1264,12 @@ COMMIT; INSERT INTO "__EFMigrationsHistory" ("MigrationId", "ProductVersion") VALUES ('20251213111207_1.7.0-FieldBasedDataModelUpdate', '9.0.4'); + +BEGIN TRANSACTION; +INSERT INTO "__EFMigrationsHistory" ("MigrationId", "ProductVersion") +VALUES ('20260130221620_2.0.0-MajorVersionBump', '9.0.4'); + +COMMIT; `; var MIGRATION_SCRIPTS = { 1: `\uFEFFBEGIN TRANSACTION; @@ -2460,7 +2466,12 @@ CREATE INDEX "IX_TotpCodes_ItemId" ON "TotpCodes" ("ItemId"); COMMIT; INSERT INTO "__EFMigrationsHistory" ("MigrationId", "ProductVersion") -VALUES ('20251213111207_1.7.0-FieldBasedDataModelUpdate', '9.0.4');` +VALUES ('20251213111207_1.7.0-FieldBasedDataModelUpdate', '9.0.4');`, + 12: `\uFEFFBEGIN TRANSACTION; +INSERT INTO "__EFMigrationsHistory" ("MigrationId", "ProductVersion") +VALUES ('20260130221620_2.0.0-MajorVersionBump', '9.0.4'); + +COMMIT;` }; // src/sql/VaultVersions.ts @@ -2547,7 +2558,14 @@ var VAULT_VERSIONS = [ version: "1.7.0", description: "Update to Field-Based Data Model", releaseVersion: "0.26.0", - compatibleUpToVersion: "0.26.0" + compatibleUpToVersion: "0.25.0" + }, + { + revision: 13, + version: "2.0.0", + description: "Update to Field-Based Data Model", + releaseVersion: "0.26.1", + compatibleUpToVersion: "0.25.0" } ]; diff --git a/apps/mobile-app/android/app/src/main/java/net/aliasvault/app/vaultstore/models/VaultSql.kt b/apps/mobile-app/android/app/src/main/java/net/aliasvault/app/vaultstore/models/VaultSql.kt index 4eaded310..7e03bfe15 100644 --- a/apps/mobile-app/android/app/src/main/java/net/aliasvault/app/vaultstore/models/VaultSql.kt +++ b/apps/mobile-app/android/app/src/main/java/net/aliasvault/app/vaultstore/models/VaultSql.kt @@ -1273,6 +1273,12 @@ COMMIT; INSERT INTO "__EFMigrationsHistory" ("MigrationId", "ProductVersion") VALUES ('20251213111207_1.7.0-FieldBasedDataModelUpdate', '9.0.4'); + +BEGIN TRANSACTION; +INSERT INTO "__EFMigrationsHistory" ("MigrationId", "ProductVersion") +VALUES ('20260130221620_2.0.0-MajorVersionBump', '9.0.4'); + +COMMIT; """.trimIndent() /** @@ -2497,6 +2503,13 @@ COMMIT; INSERT INTO "__EFMigrationsHistory" ("MigrationId", "ProductVersion") VALUES ('20251213111207_1.7.0-FieldBasedDataModelUpdate', '9.0.4'); """.trimIndent(), + 12 to """ +BEGIN TRANSACTION; +INSERT INTO "__EFMigrationsHistory" ("MigrationId", "ProductVersion") +VALUES ('20260130221620_2.0.0-MajorVersionBump', '9.0.4'); + +COMMIT; + """.trimIndent(), ) /** diff --git a/apps/mobile-app/android/app/src/main/java/net/aliasvault/app/vaultstore/models/VaultVersions.kt b/apps/mobile-app/android/app/src/main/java/net/aliasvault/app/vaultstore/models/VaultVersions.kt index 4eb1dacf3..6c59a7c9d 100644 --- a/apps/mobile-app/android/app/src/main/java/net/aliasvault/app/vaultstore/models/VaultVersions.kt +++ b/apps/mobile-app/android/app/src/main/java/net/aliasvault/app/vaultstore/models/VaultVersions.kt @@ -111,7 +111,14 @@ object VaultVersions { version = "1.7.0", description = "Update to Field-Based Data Model", releaseVersion = "0.26.0", - compatibleUpToVersion = "0.26.0", + compatibleUpToVersion = "0.25.0", + ), + VaultVersion( + revision = 13, + version = "2.0.0", + description = "Update to Field-Based Data Model", + releaseVersion = "0.26.1", + compatibleUpToVersion = "0.25.0", ), ) diff --git a/apps/mobile-app/ios/VaultModels/VaultSql.swift b/apps/mobile-app/ios/VaultModels/VaultSql.swift index ff6057edb..65e00e416 100644 --- a/apps/mobile-app/ios/VaultModels/VaultSql.swift +++ b/apps/mobile-app/ios/VaultModels/VaultSql.swift @@ -1269,6 +1269,12 @@ public struct VaultSql { INSERT INTO \"__EFMigrationsHistory\" (\"MigrationId\", \"ProductVersion\") VALUES ('20251213111207_1.7.0-FieldBasedDataModelUpdate', '9.0.4'); + + BEGIN TRANSACTION; + INSERT INTO \"__EFMigrationsHistory\" (\"MigrationId\", \"ProductVersion\") + VALUES ('20260130221620_2.0.0-MajorVersionBump', '9.0.4'); + + COMMIT; """ /// Migration SQL scripts indexed by migration number. @@ -2490,6 +2496,13 @@ public struct VaultSql { INSERT INTO \"__EFMigrationsHistory\" (\"MigrationId\", \"ProductVersion\") VALUES ('20251213111207_1.7.0-FieldBasedDataModelUpdate', '9.0.4'); + """, + 12: """ + BEGIN TRANSACTION; + INSERT INTO \"__EFMigrationsHistory\" (\"MigrationId\", \"ProductVersion\") + VALUES ('20260130221620_2.0.0-MajorVersionBump', '9.0.4'); + + COMMIT; """ ] diff --git a/apps/mobile-app/ios/VaultModels/VaultVersions.swift b/apps/mobile-app/ios/VaultModels/VaultVersions.swift index feec6c09d..254cb41e9 100644 --- a/apps/mobile-app/ios/VaultModels/VaultVersions.swift +++ b/apps/mobile-app/ios/VaultModels/VaultVersions.swift @@ -109,7 +109,14 @@ public struct VaultVersions { version: "1.7.0", description: "Update to Field-Based Data Model", releaseVersion: "0.26.0", - compatibleUpToVersion: "0.26.0" + compatibleUpToVersion: "0.25.0" + ), + VaultVersion( + revision: 13, + version: "2.0.0", + description: "Update to Field-Based Data Model", + releaseVersion: "0.26.1", + compatibleUpToVersion: "0.25.0" ) ] diff --git a/apps/mobile-app/utils/dist/core/vault/index.d.mts b/apps/mobile-app/utils/dist/core/vault/index.d.mts index 033a999f0..0ee327dbe 100644 --- a/apps/mobile-app/utils/dist/core/vault/index.d.mts +++ b/apps/mobile-app/utils/dist/core/vault/index.d.mts @@ -122,7 +122,7 @@ declare const VAULT_VERSIONS: VaultVersion[]; * Complete database schema SQL (latest version) * Auto-generated from EF Core migrations */ -declare const COMPLETE_SCHEMA_SQL = "\n\uFEFFCREATE TABLE IF NOT EXISTS \"__EFMigrationsHistory\" (\n \"MigrationId\" TEXT NOT NULL CONSTRAINT \"PK___EFMigrationsHistory\" PRIMARY KEY,\n \"ProductVersion\" TEXT NOT NULL\n);\n\nBEGIN TRANSACTION;\nCREATE TABLE \"Aliases\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_Aliases\" PRIMARY KEY,\n \"Gender\" VARCHAR NULL,\n \"FirstName\" VARCHAR NULL,\n \"LastName\" VARCHAR NULL,\n \"NickName\" VARCHAR NULL,\n \"BirthDate\" TEXT NOT NULL,\n \"AddressStreet\" VARCHAR NULL,\n \"AddressCity\" VARCHAR NULL,\n \"AddressState\" VARCHAR NULL,\n \"AddressZipCode\" VARCHAR NULL,\n \"AddressCountry\" VARCHAR NULL,\n \"Hobbies\" TEXT NULL,\n \"EmailPrefix\" TEXT NULL,\n \"PhoneMobile\" TEXT NULL,\n \"BankAccountIBAN\" TEXT NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"UpdatedAt\" TEXT NOT NULL\n);\n\nCREATE TABLE \"Services\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_Services\" PRIMARY KEY,\n \"Name\" TEXT NULL,\n \"Url\" TEXT NULL,\n \"Logo\" BLOB NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"UpdatedAt\" TEXT NOT NULL\n);\n\nCREATE TABLE \"Credentials\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_Credentials\" PRIMARY KEY,\n \"AliasId\" TEXT NOT NULL,\n \"Notes\" TEXT NULL,\n \"Username\" TEXT NOT NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"UpdatedAt\" TEXT NOT NULL,\n \"ServiceId\" TEXT NOT NULL,\n CONSTRAINT \"FK_Credentials_Aliases_AliasId\" FOREIGN KEY (\"AliasId\") REFERENCES \"Aliases\" (\"Id\") ON DELETE CASCADE,\n CONSTRAINT \"FK_Credentials_Services_ServiceId\" FOREIGN KEY (\"ServiceId\") REFERENCES \"Services\" (\"Id\") ON DELETE CASCADE\n);\n\nCREATE TABLE \"Attachment\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_Attachment\" PRIMARY KEY,\n \"Filename\" TEXT NOT NULL,\n \"Blob\" BLOB NOT NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"UpdatedAt\" TEXT NOT NULL,\n \"CredentialId\" TEXT NOT NULL,\n CONSTRAINT \"FK_Attachment_Credentials_CredentialId\" FOREIGN KEY (\"CredentialId\") REFERENCES \"Credentials\" (\"Id\") ON DELETE CASCADE\n);\n\nCREATE TABLE \"Passwords\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_Passwords\" PRIMARY KEY,\n \"Value\" TEXT NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"UpdatedAt\" TEXT NOT NULL,\n \"CredentialId\" TEXT NOT NULL,\n CONSTRAINT \"FK_Passwords_Credentials_CredentialId\" FOREIGN KEY (\"CredentialId\") REFERENCES \"Credentials\" (\"Id\") ON DELETE CASCADE\n);\n\nCREATE INDEX \"IX_Attachment_CredentialId\" ON \"Attachment\" (\"CredentialId\");\n\nCREATE INDEX \"IX_Credentials_AliasId\" ON \"Credentials\" (\"AliasId\");\n\nCREATE INDEX \"IX_Credentials_ServiceId\" ON \"Credentials\" (\"ServiceId\");\n\nCREATE INDEX \"IX_Passwords_CredentialId\" ON \"Passwords\" (\"CredentialId\");\n\nINSERT INTO \"__EFMigrationsHistory\" (\"MigrationId\", \"ProductVersion\")\nVALUES ('20240708094944_1.0.0-InitialMigration', '9.0.4');\n\nINSERT INTO \"__EFMigrationsHistory\" (\"MigrationId\", \"ProductVersion\")\nVALUES ('20240708224522_1.0.1-EmptyTestMigration', '9.0.4');\n\nALTER TABLE \"Aliases\" RENAME COLUMN \"EmailPrefix\" TO \"Email\";\n\nINSERT INTO \"__EFMigrationsHistory\" (\"MigrationId\", \"ProductVersion\")\nVALUES ('20240711204207_1.0.2-ChangeEmailColumn', '9.0.4');\n\nCREATE TABLE \"EncryptionKeys\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_EncryptionKeys\" PRIMARY KEY,\n \"PublicKey\" TEXT NOT NULL,\n \"PrivateKey\" TEXT NOT NULL,\n \"IsPrimary\" INTEGER NOT NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"UpdatedAt\" TEXT NOT NULL\n);\n\nINSERT INTO \"__EFMigrationsHistory\" (\"MigrationId\", \"ProductVersion\")\nVALUES ('20240729105618_1.1.0-AddPkiTables', '9.0.4');\n\nCREATE TABLE \"Settings\" (\n \"Key\" TEXT NOT NULL CONSTRAINT \"PK_Settings\" PRIMARY KEY,\n \"Value\" TEXT NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"UpdatedAt\" TEXT NOT NULL\n);\n\nINSERT INTO \"__EFMigrationsHistory\" (\"MigrationId\", \"ProductVersion\")\nVALUES ('20240805073413_1.2.0-AddSettingsTable', '9.0.4');\n\nCREATE TABLE \"ef_temp_Aliases\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_Aliases\" PRIMARY KEY,\n \"BirthDate\" TEXT NOT NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"Email\" TEXT NULL,\n \"FirstName\" VARCHAR NULL,\n \"Gender\" VARCHAR NULL,\n \"LastName\" VARCHAR NULL,\n \"NickName\" VARCHAR NULL,\n \"UpdatedAt\" TEXT NOT NULL\n);\n\nINSERT INTO \"ef_temp_Aliases\" (\"Id\", \"BirthDate\", \"CreatedAt\", \"Email\", \"FirstName\", \"Gender\", \"LastName\", \"NickName\", \"UpdatedAt\")\nSELECT \"Id\", \"BirthDate\", \"CreatedAt\", \"Email\", \"FirstName\", \"Gender\", \"LastName\", \"NickName\", \"UpdatedAt\"\nFROM \"Aliases\";\n\nCOMMIT;\n\nPRAGMA foreign_keys = 0;\n\nBEGIN TRANSACTION;\nDROP TABLE \"Aliases\";\n\nALTER TABLE \"ef_temp_Aliases\" RENAME TO \"Aliases\";\n\nCOMMIT;\n\nPRAGMA foreign_keys = 1;\n\nINSERT INTO \"__EFMigrationsHistory\" (\"MigrationId\", \"ProductVersion\")\nVALUES ('20240805122422_1.3.0-UpdateIdentityStructure', '9.0.4');\n\nBEGIN TRANSACTION;\nCREATE TABLE \"ef_temp_Credentials\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_Credentials\" PRIMARY KEY,\n \"AliasId\" TEXT NOT NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"Notes\" TEXT NULL,\n \"ServiceId\" TEXT NOT NULL,\n \"UpdatedAt\" TEXT NOT NULL,\n \"Username\" TEXT NULL,\n CONSTRAINT \"FK_Credentials_Aliases_AliasId\" FOREIGN KEY (\"AliasId\") REFERENCES \"Aliases\" (\"Id\") ON DELETE CASCADE,\n CONSTRAINT \"FK_Credentials_Services_ServiceId\" FOREIGN KEY (\"ServiceId\") REFERENCES \"Services\" (\"Id\") ON DELETE CASCADE\n);\n\nINSERT INTO \"ef_temp_Credentials\" (\"Id\", \"AliasId\", \"CreatedAt\", \"Notes\", \"ServiceId\", \"UpdatedAt\", \"Username\")\nSELECT \"Id\", \"AliasId\", \"CreatedAt\", \"Notes\", \"ServiceId\", \"UpdatedAt\", \"Username\"\nFROM \"Credentials\";\n\nCOMMIT;\n\nPRAGMA foreign_keys = 0;\n\nBEGIN TRANSACTION;\nDROP TABLE \"Credentials\";\n\nALTER TABLE \"ef_temp_Credentials\" RENAME TO \"Credentials\";\n\nCOMMIT;\n\nPRAGMA foreign_keys = 1;\n\nBEGIN TRANSACTION;\nCREATE INDEX \"IX_Credentials_AliasId\" ON \"Credentials\" (\"AliasId\");\n\nCREATE INDEX \"IX_Credentials_ServiceId\" ON \"Credentials\" (\"ServiceId\");\n\nCOMMIT;\n\nINSERT INTO \"__EFMigrationsHistory\" (\"MigrationId\", \"ProductVersion\")\nVALUES ('20240812141727_1.3.1-MakeUsernameOptional', '9.0.4');\n\nBEGIN TRANSACTION;\nALTER TABLE \"Settings\" ADD \"IsDeleted\" INTEGER NOT NULL DEFAULT 0;\n\nALTER TABLE \"Services\" ADD \"IsDeleted\" INTEGER NOT NULL DEFAULT 0;\n\nALTER TABLE \"Passwords\" ADD \"IsDeleted\" INTEGER NOT NULL DEFAULT 0;\n\nALTER TABLE \"EncryptionKeys\" ADD \"IsDeleted\" INTEGER NOT NULL DEFAULT 0;\n\nALTER TABLE \"Credentials\" ADD \"IsDeleted\" INTEGER NOT NULL DEFAULT 0;\n\nALTER TABLE \"Attachment\" ADD \"IsDeleted\" INTEGER NOT NULL DEFAULT 0;\n\nALTER TABLE \"Aliases\" ADD \"IsDeleted\" INTEGER NOT NULL DEFAULT 0;\n\nINSERT INTO \"__EFMigrationsHistory\" (\"MigrationId\", \"ProductVersion\")\nVALUES ('20240916105320_1.4.0-AddSyncSupport', '9.0.4');\n\nALTER TABLE \"Attachment\" RENAME TO \"Attachments\";\n\nCREATE TABLE \"ef_temp_Attachments\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_Attachments\" PRIMARY KEY,\n \"Blob\" BLOB NOT NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"CredentialId\" TEXT NOT NULL,\n \"Filename\" TEXT NOT NULL,\n \"IsDeleted\" INTEGER NOT NULL,\n \"UpdatedAt\" TEXT NOT NULL,\n CONSTRAINT \"FK_Attachments_Credentials_CredentialId\" FOREIGN KEY (\"CredentialId\") REFERENCES \"Credentials\" (\"Id\") ON DELETE CASCADE\n);\n\nINSERT INTO \"ef_temp_Attachments\" (\"Id\", \"Blob\", \"CreatedAt\", \"CredentialId\", \"Filename\", \"IsDeleted\", \"UpdatedAt\")\nSELECT \"Id\", \"Blob\", \"CreatedAt\", \"CredentialId\", \"Filename\", \"IsDeleted\", \"UpdatedAt\"\nFROM \"Attachments\";\n\nCOMMIT;\n\nPRAGMA foreign_keys = 0;\n\nBEGIN TRANSACTION;\nDROP TABLE \"Attachments\";\n\nALTER TABLE \"ef_temp_Attachments\" RENAME TO \"Attachments\";\n\nCOMMIT;\n\nPRAGMA foreign_keys = 1;\n\nBEGIN TRANSACTION;\nCREATE INDEX \"IX_Attachments_CredentialId\" ON \"Attachments\" (\"CredentialId\");\n\nCOMMIT;\n\nINSERT INTO \"__EFMigrationsHistory\" (\"MigrationId\", \"ProductVersion\")\nVALUES ('20240917191243_1.4.1-RenameAttachmentsPlural', '9.0.4');\n\nBEGIN TRANSACTION;\nCREATE TABLE \"TotpCodes\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_TotpCodes\" PRIMARY KEY,\n \"Name\" TEXT NOT NULL,\n \"SecretKey\" TEXT NOT NULL,\n \"CredentialId\" TEXT NOT NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"UpdatedAt\" TEXT NOT NULL,\n \"IsDeleted\" INTEGER NOT NULL,\n CONSTRAINT \"FK_TotpCodes_Credentials_CredentialId\" FOREIGN KEY (\"CredentialId\") REFERENCES \"Credentials\" (\"Id\") ON DELETE CASCADE\n);\n\nCREATE INDEX \"IX_TotpCodes_CredentialId\" ON \"TotpCodes\" (\"CredentialId\");\n\nINSERT INTO \"__EFMigrationsHistory\" (\"MigrationId\", \"ProductVersion\")\nVALUES ('20250310131554_1.5.0-AddTotpCodes', '9.0.4');\n\n\nPRAGMA foreign_keys = OFF;\n\n-- Clean up any existing temp tables first\nDROP TABLE IF EXISTS \"__EFMigrationsHistory_temp\";\nDROP TABLE IF EXISTS \"Aliases_temp\";\nDROP TABLE IF EXISTS \"Services_temp\";\nDROP TABLE IF EXISTS \"EncryptionKeys_temp\";\nDROP TABLE IF EXISTS \"Settings_temp\";\nDROP TABLE IF EXISTS \"Credentials_temp\";\nDROP TABLE IF EXISTS \"Attachments_temp\";\nDROP TABLE IF EXISTS \"Passwords_temp\";\nDROP TABLE IF EXISTS \"TotpCodes_temp\";\n\n-- Create backup tables for all data\nCREATE TABLE \"__EFMigrationsHistory_temp\" AS SELECT * FROM \"__EFMigrationsHistory\";\nCREATE TABLE \"Aliases_temp\" AS SELECT * FROM \"Aliases\";\nCREATE TABLE \"Services_temp\" AS SELECT * FROM \"Services\";\nCREATE TABLE \"EncryptionKeys_temp\" AS SELECT * FROM \"EncryptionKeys\";\nCREATE TABLE \"Settings_temp\" AS SELECT * FROM \"Settings\";\nCREATE TABLE \"Credentials_temp\" AS SELECT * FROM \"Credentials\";\nCREATE TABLE \"Attachments_temp\" AS SELECT * FROM \"Attachments\";\nCREATE TABLE \"Passwords_temp\" AS SELECT * FROM \"Passwords\";\nCREATE TABLE \"TotpCodes_temp\" AS SELECT * FROM \"TotpCodes\";\n\n-- Delete orphaned records that do not have a valid FK to the credential object\nDELETE FROM \"Attachments_temp\" WHERE \"CredentialId\" NOT IN (SELECT \"Id\" FROM \"Credentials_temp\");\nDELETE FROM \"Passwords_temp\" WHERE \"CredentialId\" NOT IN (SELECT \"Id\" FROM \"Credentials_temp\");\nDELETE FROM \"TotpCodes_temp\" WHERE \"CredentialId\" NOT IN (SELECT \"Id\" FROM \"Credentials_temp\");\n\n-- Delete orphaned credentials that do not have valid FKs to alias or service objects\nDELETE FROM \"Credentials_temp\" WHERE \"AliasId\" NOT IN (SELECT \"Id\" FROM \"Aliases_temp\");\nDELETE FROM \"Credentials_temp\" WHERE \"ServiceId\" NOT IN (SELECT \"Id\" FROM \"Services_temp\");\n\n-- After cleaning credentials, clean dependent tables again in case we removed credentials\nDELETE FROM \"Attachments_temp\" WHERE \"CredentialId\" NOT IN (SELECT \"Id\" FROM \"Credentials_temp\");\nDELETE FROM \"Passwords_temp\" WHERE \"CredentialId\" NOT IN (SELECT \"Id\" FROM \"Credentials_temp\");\nDELETE FROM \"TotpCodes_temp\" WHERE \"CredentialId\" NOT IN (SELECT \"Id\" FROM \"Credentials_temp\");\n\n-- Drop all existing tables\nDROP TABLE \"TotpCodes\";\nDROP TABLE \"Passwords\";\nDROP TABLE \"Attachments\";\nDROP TABLE \"Credentials\";\nDROP TABLE \"Settings\";\nDROP TABLE \"EncryptionKeys\";\nDROP TABLE \"Services\";\nDROP TABLE \"Aliases\";\nDROP TABLE \"__EFMigrationsHistory\";\n\n-- Recreate tables with proper constraints (no dependencies first)\nCREATE TABLE \"__EFMigrationsHistory\" (\n \"MigrationId\" TEXT NOT NULL CONSTRAINT \"PK___EFMigrationsHistory\" PRIMARY KEY,\n \"ProductVersion\" TEXT NOT NULL\n);\n\nCREATE TABLE \"Aliases\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_Aliases\" PRIMARY KEY,\n \"BirthDate\" TEXT NOT NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"Email\" TEXT NULL,\n \"FirstName\" VARCHAR NULL,\n \"Gender\" VARCHAR NULL,\n \"LastName\" VARCHAR NULL,\n \"NickName\" VARCHAR NULL,\n \"UpdatedAt\" TEXT NOT NULL,\n \"IsDeleted\" INTEGER NOT NULL DEFAULT 0\n);\n\nCREATE TABLE \"Services\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_Services\" PRIMARY KEY,\n \"Name\" TEXT NULL,\n \"Url\" TEXT NULL,\n \"Logo\" BLOB NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"UpdatedAt\" TEXT NOT NULL,\n \"IsDeleted\" INTEGER NOT NULL DEFAULT 0\n);\n\nCREATE TABLE \"EncryptionKeys\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_EncryptionKeys\" PRIMARY KEY,\n \"PublicKey\" TEXT NOT NULL,\n \"PrivateKey\" TEXT NOT NULL,\n \"IsPrimary\" INTEGER NOT NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"UpdatedAt\" TEXT NOT NULL,\n \"IsDeleted\" INTEGER NOT NULL DEFAULT 0\n);\n\nCREATE TABLE \"Settings\" (\n \"Key\" TEXT NOT NULL CONSTRAINT \"PK_Settings\" PRIMARY KEY,\n \"Value\" TEXT NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"UpdatedAt\" TEXT NOT NULL,\n \"IsDeleted\" INTEGER NOT NULL DEFAULT 0\n);\n\n-- Tables with foreign keys\nCREATE TABLE \"Credentials\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_Credentials\" PRIMARY KEY,\n \"AliasId\" TEXT NOT NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"Notes\" TEXT NULL,\n \"ServiceId\" TEXT NOT NULL,\n \"UpdatedAt\" TEXT NOT NULL,\n \"Username\" TEXT NULL,\n \"IsDeleted\" INTEGER NOT NULL DEFAULT 0,\n CONSTRAINT \"FK_Credentials_Aliases_AliasId\" FOREIGN KEY (\"AliasId\") REFERENCES \"Aliases\" (\"Id\") ON DELETE CASCADE,\n CONSTRAINT \"FK_Credentials_Services_ServiceId\" FOREIGN KEY (\"ServiceId\") REFERENCES \"Services\" (\"Id\") ON DELETE CASCADE\n);\n\nCREATE TABLE \"Attachments\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_Attachments\" PRIMARY KEY,\n \"Blob\" BLOB NOT NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"CredentialId\" TEXT NOT NULL,\n \"Filename\" TEXT NOT NULL,\n \"IsDeleted\" INTEGER NOT NULL DEFAULT 0,\n \"UpdatedAt\" TEXT NOT NULL,\n CONSTRAINT \"FK_Attachments_Credentials_CredentialId\" FOREIGN KEY (\"CredentialId\") REFERENCES \"Credentials\" (\"Id\") ON DELETE CASCADE\n);\n\nCREATE TABLE \"Passwords\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_Passwords\" PRIMARY KEY,\n \"Value\" TEXT NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"UpdatedAt\" TEXT NOT NULL,\n \"CredentialId\" TEXT NOT NULL,\n \"IsDeleted\" INTEGER NOT NULL DEFAULT 0,\n CONSTRAINT \"FK_Passwords_Credentials_CredentialId\" FOREIGN KEY (\"CredentialId\") REFERENCES \"Credentials\" (\"Id\") ON DELETE CASCADE\n);\n\nCREATE TABLE \"TotpCodes\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_TotpCodes\" PRIMARY KEY,\n \"Name\" TEXT NOT NULL,\n \"SecretKey\" TEXT NOT NULL,\n \"CredentialId\" TEXT NOT NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"UpdatedAt\" TEXT NOT NULL,\n \"IsDeleted\" INTEGER NOT NULL DEFAULT 0,\n CONSTRAINT \"FK_TotpCodes_Credentials_CredentialId\" FOREIGN KEY (\"CredentialId\") REFERENCES \"Credentials\" (\"Id\") ON DELETE CASCADE\n);\n\n\n-- Restore data from temp tables\nINSERT INTO \"__EFMigrationsHistory\" SELECT * FROM \"__EFMigrationsHistory_temp\";\nINSERT INTO \"Aliases\" SELECT * FROM \"Aliases_temp\";\nINSERT INTO \"Services\" SELECT * FROM \"Services_temp\";\nINSERT INTO \"EncryptionKeys\" SELECT * FROM \"EncryptionKeys_temp\";\nINSERT INTO \"Settings\" SELECT * FROM \"Settings_temp\";\nINSERT INTO \"Credentials\" SELECT * FROM \"Credentials_temp\";\nINSERT INTO \"Attachments\" SELECT * FROM \"Attachments_temp\";\nINSERT INTO \"Passwords\" SELECT * FROM \"Passwords_temp\";\nINSERT INTO \"TotpCodes\" SELECT * FROM \"TotpCodes_temp\";\n\n-- =====================================================================================\n-- Date Format Normalization Migration\n-- =====================================================================================\n-- This migration normalizes ALL date fields to the standard format: 'yyyy-MM-dd HH:mm:ss.fff'\n-- Previously the different clients used different date formats which complicate date parsing.\n-- From version 0.24.0 onwards, all new dates are stored in this standard format.\n\n-- Update Aliases table (CreatedAt, UpdatedAt, BirthDate)\nUPDATE \"Aliases\" SET \"CreatedAt\" =\n CASE\n -- Already in correct format (yyyy-MM-dd HH:mm:ss.fff) - no change\n WHEN \"CreatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9] [0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9][0-9][0-9]'\n THEN \"CreatedAt\"\n\n -- ISO 8601 with milliseconds (yyyy-MM-ddTHH:mm:ss.fffZ) -> Replace T with space, remove Z and everything after .fff\n WHEN \"CreatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]T[0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9]*'\n THEN substr(\"CreatedAt\", 1, 10) || ' ' || substr(\"CreatedAt\", 12, 12)\n\n -- Without milliseconds (yyyy-MM-dd HH:mm:ss or yyyy-MM-ddTHH:mm:ssZ) -> Add .000\n WHEN \"CreatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9][T ][0-9][0-9]:[0-9][0-9]:[0-9][0-9]*'\n THEN substr(\"CreatedAt\", 1, 10) || ' ' || substr(replace(\"CreatedAt\", 'T', ' '), 12, 8) || '.000'\n\n -- Fallback: if none match, keep as-is (edge case)\n ELSE \"CreatedAt\"\n END;\n\nUPDATE \"Aliases\" SET \"UpdatedAt\" =\n CASE\n WHEN \"UpdatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9] [0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9][0-9][0-9]'\n THEN \"UpdatedAt\"\n WHEN \"UpdatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]T[0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9]*'\n THEN substr(\"UpdatedAt\", 1, 10) || ' ' || substr(\"UpdatedAt\", 12, 12)\n WHEN \"UpdatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9][T ][0-9][0-9]:[0-9][0-9]:[0-9][0-9]*'\n THEN substr(\"UpdatedAt\", 1, 10) || ' ' || substr(replace(\"UpdatedAt\", 'T', ' '), 12, 8) || '.000'\n ELSE \"UpdatedAt\"\n END;\n\n-- BirthDate: Always set time to 00:00:00 (no milliseconds for birth dates)\nUPDATE \"Aliases\" SET \"BirthDate\" =\n CASE\n -- If empty or already '0001-01-01 00:00:00', keep as-is\n WHEN \"BirthDate\" = '' OR \"BirthDate\" = '0001-01-01 00:00:00'\n THEN \"BirthDate\"\n\n -- If already in correct format (yyyy-MM-dd 00:00:00), keep as-is\n WHEN \"BirthDate\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9] 00:00:00'\n THEN \"BirthDate\"\n\n -- Extract date part and set time to 00:00:00\n WHEN \"BirthDate\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]*'\n THEN substr(\"BirthDate\", 1, 10) || ' 00:00:00'\n\n -- Fallback\n ELSE \"BirthDate\"\n END;\n\n-- Update Services table (CreatedAt, UpdatedAt)\nUPDATE \"Services\" SET \"CreatedAt\" =\n CASE\n WHEN \"CreatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9] [0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9][0-9][0-9]'\n THEN \"CreatedAt\"\n WHEN \"CreatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]T[0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9]*'\n THEN substr(\"CreatedAt\", 1, 10) || ' ' || substr(\"CreatedAt\", 12, 12)\n WHEN \"CreatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9][T ][0-9][0-9]:[0-9][0-9]:[0-9][0-9]*'\n THEN substr(\"CreatedAt\", 1, 10) || ' ' || substr(replace(\"CreatedAt\", 'T', ' '), 12, 8) || '.000'\n ELSE \"CreatedAt\"\n END;\n\nUPDATE \"Services\" SET \"UpdatedAt\" =\n CASE\n WHEN \"UpdatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9] [0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9][0-9][0-9]'\n THEN \"UpdatedAt\"\n WHEN \"UpdatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]T[0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9]*'\n THEN substr(\"UpdatedAt\", 1, 10) || ' ' || substr(\"UpdatedAt\", 12, 12)\n WHEN \"UpdatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9][T ][0-9][0-9]:[0-9][0-9]:[0-9][0-9]*'\n THEN substr(\"UpdatedAt\", 1, 10) || ' ' || substr(replace(\"UpdatedAt\", 'T', ' '), 12, 8) || '.000'\n ELSE \"UpdatedAt\"\n END;\n\n-- Update EncryptionKeys table (CreatedAt, UpdatedAt)\nUPDATE \"EncryptionKeys\" SET \"CreatedAt\" =\n CASE\n WHEN \"CreatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9] [0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9][0-9][0-9]'\n THEN \"CreatedAt\"\n WHEN \"CreatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]T[0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9]*'\n THEN substr(\"CreatedAt\", 1, 10) || ' ' || substr(\"CreatedAt\", 12, 12)\n WHEN \"CreatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9][T ][0-9][0-9]:[0-9][0-9]:[0-9][0-9]*'\n THEN substr(\"CreatedAt\", 1, 10) || ' ' || substr(replace(\"CreatedAt\", 'T', ' '), 12, 8) || '.000'\n ELSE \"CreatedAt\"\n END;\n\nUPDATE \"EncryptionKeys\" SET \"UpdatedAt\" =\n CASE\n WHEN \"UpdatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9] [0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9][0-9][0-9]'\n THEN \"UpdatedAt\"\n WHEN \"UpdatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]T[0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9]*'\n THEN substr(\"UpdatedAt\", 1, 10) || ' ' || substr(\"UpdatedAt\", 12, 12)\n WHEN \"UpdatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9][T ][0-9][0-9]:[0-9][0-9]:[0-9][0-9]*'\n THEN substr(\"UpdatedAt\", 1, 10) || ' ' || substr(replace(\"UpdatedAt\", 'T', ' '), 12, 8) || '.000'\n ELSE \"UpdatedAt\"\n END;\n\n-- Update Settings table (CreatedAt, UpdatedAt)\nUPDATE \"Settings\" SET \"CreatedAt\" =\n CASE\n WHEN \"CreatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9] [0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9][0-9][0-9]'\n THEN \"CreatedAt\"\n WHEN \"CreatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]T[0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9]*'\n THEN substr(\"CreatedAt\", 1, 10) || ' ' || substr(\"CreatedAt\", 12, 12)\n WHEN \"CreatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9][T ][0-9][0-9]:[0-9][0-9]:[0-9][0-9]*'\n THEN substr(\"CreatedAt\", 1, 10) || ' ' || substr(replace(\"CreatedAt\", 'T', ' '), 12, 8) || '.000'\n ELSE \"CreatedAt\"\n END;\n\nUPDATE \"Settings\" SET \"UpdatedAt\" =\n CASE\n WHEN \"UpdatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9] [0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9][0-9][0-9]'\n THEN \"UpdatedAt\"\n WHEN \"UpdatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]T[0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9]*'\n THEN substr(\"UpdatedAt\", 1, 10) || ' ' || substr(\"UpdatedAt\", 12, 12)\n WHEN \"UpdatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9][T ][0-9][0-9]:[0-9][0-9]:[0-9][0-9]*'\n THEN substr(\"UpdatedAt\", 1, 10) || ' ' || substr(replace(\"UpdatedAt\", 'T', ' '), 12, 8) || '.000'\n ELSE \"UpdatedAt\"\n END;\n\n-- Update Credentials table (CreatedAt, UpdatedAt)\nUPDATE \"Credentials\" SET \"CreatedAt\" =\n CASE\n WHEN \"CreatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9] [0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9][0-9][0-9]'\n THEN \"CreatedAt\"\n WHEN \"CreatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]T[0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9]*'\n THEN substr(\"CreatedAt\", 1, 10) || ' ' || substr(\"CreatedAt\", 12, 12)\n WHEN \"CreatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9][T ][0-9][0-9]:[0-9][0-9]:[0-9][0-9]*'\n THEN substr(\"CreatedAt\", 1, 10) || ' ' || substr(replace(\"CreatedAt\", 'T', ' '), 12, 8) || '.000'\n ELSE \"CreatedAt\"\n END;\n\nUPDATE \"Credentials\" SET \"UpdatedAt\" =\n CASE\n WHEN \"UpdatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9] [0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9][0-9][0-9]'\n THEN \"UpdatedAt\"\n WHEN \"UpdatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]T[0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9]*'\n THEN substr(\"UpdatedAt\", 1, 10) || ' ' || substr(\"UpdatedAt\", 12, 12)\n WHEN \"UpdatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9][T ][0-9][0-9]:[0-9][0-9]:[0-9][0-9]*'\n THEN substr(\"UpdatedAt\", 1, 10) || ' ' || substr(replace(\"UpdatedAt\", 'T', ' '), 12, 8) || '.000'\n ELSE \"UpdatedAt\"\n END;\n\n-- Update Attachments table (CreatedAt, UpdatedAt)\nUPDATE \"Attachments\" SET \"CreatedAt\" =\n CASE\n WHEN \"CreatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9] [0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9][0-9][0-9]'\n THEN \"CreatedAt\"\n WHEN \"CreatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]T[0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9]*'\n THEN substr(\"CreatedAt\", 1, 10) || ' ' || substr(\"CreatedAt\", 12, 12)\n WHEN \"CreatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9][T ][0-9][0-9]:[0-9][0-9]:[0-9][0-9]*'\n THEN substr(\"CreatedAt\", 1, 10) || ' ' || substr(replace(\"CreatedAt\", 'T', ' '), 12, 8) || '.000'\n ELSE \"CreatedAt\"\n END;\n\nUPDATE \"Attachments\" SET \"UpdatedAt\" =\n CASE\n WHEN \"UpdatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9] [0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9][0-9][0-9]'\n THEN \"UpdatedAt\"\n WHEN \"UpdatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]T[0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9]*'\n THEN substr(\"UpdatedAt\", 1, 10) || ' ' || substr(\"UpdatedAt\", 12, 12)\n WHEN \"UpdatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9][T ][0-9][0-9]:[0-9][0-9]:[0-9][0-9]*'\n THEN substr(\"UpdatedAt\", 1, 10) || ' ' || substr(replace(\"UpdatedAt\", 'T', ' '), 12, 8) || '.000'\n ELSE \"UpdatedAt\"\n END;\n\n-- Update Passwords table (CreatedAt, UpdatedAt)\nUPDATE \"Passwords\" SET \"CreatedAt\" =\n CASE\n WHEN \"CreatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9] [0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9][0-9][0-9]'\n THEN \"CreatedAt\"\n WHEN \"CreatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]T[0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9]*'\n THEN substr(\"CreatedAt\", 1, 10) || ' ' || substr(\"CreatedAt\", 12, 12)\n WHEN \"CreatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9][T ][0-9][0-9]:[0-9][0-9]:[0-9][0-9]*'\n THEN substr(\"CreatedAt\", 1, 10) || ' ' || substr(replace(\"CreatedAt\", 'T', ' '), 12, 8) || '.000'\n ELSE \"CreatedAt\"\n END;\n\nUPDATE \"Passwords\" SET \"UpdatedAt\" =\n CASE\n WHEN \"UpdatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9] [0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9][0-9][0-9]'\n THEN \"UpdatedAt\"\n WHEN \"UpdatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]T[0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9]*'\n THEN substr(\"UpdatedAt\", 1, 10) || ' ' || substr(\"UpdatedAt\", 12, 12)\n WHEN \"UpdatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9][T ][0-9][0-9]:[0-9][0-9]:[0-9][0-9]*'\n THEN substr(\"UpdatedAt\", 1, 10) || ' ' || substr(replace(\"UpdatedAt\", 'T', ' '), 12, 8) || '.000'\n ELSE \"UpdatedAt\"\n END;\n\n-- Update TotpCodes table (CreatedAt, UpdatedAt)\nUPDATE \"TotpCodes\" SET \"CreatedAt\" =\n CASE\n WHEN \"CreatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9] [0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9][0-9][0-9]'\n THEN \"CreatedAt\"\n WHEN \"CreatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]T[0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9]*'\n THEN substr(\"CreatedAt\", 1, 10) || ' ' || substr(\"CreatedAt\", 12, 12)\n WHEN \"CreatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9][T ][0-9][0-9]:[0-9][0-9]:[0-9][0-9]*'\n THEN substr(\"CreatedAt\", 1, 10) || ' ' || substr(replace(\"CreatedAt\", 'T', ' '), 12, 8) || '.000'\n ELSE \"CreatedAt\"\n END;\n\nUPDATE \"TotpCodes\" SET \"UpdatedAt\" =\n CASE\n WHEN \"UpdatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9] [0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9][0-9][0-9]'\n THEN \"UpdatedAt\"\n WHEN \"UpdatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]T[0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9]*'\n THEN substr(\"UpdatedAt\", 1, 10) || ' ' || substr(\"UpdatedAt\", 12, 12)\n WHEN \"UpdatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9][T ][0-9][0-9]:[0-9][0-9]:[0-9][0-9]*'\n THEN substr(\"UpdatedAt\", 1, 10) || ' ' || substr(replace(\"UpdatedAt\", 'T', ' '), 12, 8) || '.000'\n ELSE \"UpdatedAt\"\n END;\n\n-- =====================================================================================\n-- End of Date Format Normalization Migration\n-- =====================================================================================\n\n-- Recreate indexes\nCREATE INDEX \"IX_Credentials_AliasId\" ON \"Credentials\" (\"AliasId\");\nCREATE INDEX \"IX_Credentials_ServiceId\" ON \"Credentials\" (\"ServiceId\");\nCREATE INDEX \"IX_Attachments_CredentialId\" ON \"Attachments\" (\"CredentialId\");\nCREATE INDEX \"IX_Passwords_CredentialId\" ON \"Passwords\" (\"CredentialId\");\nCREATE INDEX \"IX_TotpCodes_CredentialId\" ON \"TotpCodes\" (\"CredentialId\");\n\n-- Clean up temp tables\nDROP TABLE \"__EFMigrationsHistory_temp\";\nDROP TABLE \"Aliases_temp\";\nDROP TABLE \"Services_temp\";\nDROP TABLE \"EncryptionKeys_temp\";\nDROP TABLE \"Settings_temp\";\nDROP TABLE \"Credentials_temp\";\nDROP TABLE \"Attachments_temp\";\nDROP TABLE \"Passwords_temp\";\nDROP TABLE \"TotpCodes_temp\";\n\nPRAGMA foreign_keys = ON;\n\n\nCREATE TABLE \"Passkeys\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_Passkeys\" PRIMARY KEY,\n \"RpId\" TEXT COLLATE NOCASE NOT NULL,\n \"UserHandle\" BLOB NOT NULL,\n \"PublicKey\" TEXT NOT NULL,\n \"PrivateKey\" TEXT NOT NULL,\n \"PrfKey\" BLOB NULL,\n \"DisplayName\" TEXT NOT NULL,\n \"AdditionalData\" BLOB NULL,\n \"CredentialId\" TEXT NOT NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"UpdatedAt\" TEXT NOT NULL,\n \"IsDeleted\" INTEGER NOT NULL,\n CONSTRAINT \"FK_Passkeys_Credentials_CredentialId\" FOREIGN KEY (\"CredentialId\") REFERENCES \"Credentials\" (\"Id\") ON DELETE CASCADE\n);\n\nCREATE INDEX \"IX_Passkeys_CredentialId\" ON \"Passkeys\" (\"CredentialId\");\n\nCREATE INDEX \"IX_Passkeys_RpId\" ON \"Passkeys\" (\"RpId\");\n\nINSERT INTO \"__EFMigrationsHistory\" (\"MigrationId\", \"ProductVersion\")\nVALUES ('20251014122838_1.6.0-AddPasskeys', '9.0.4');\n\nALTER TABLE \"TotpCodes\" RENAME COLUMN \"CredentialId\" TO \"ItemId\";\n\nDROP INDEX IF EXISTS \"IX_TotpCodes_CredentialId\";\n\nCREATE INDEX IF NOT EXISTS \"IX_TotpCodes_ItemId\" ON \"TotpCodes\" (\"ItemId\");\n\nALTER TABLE \"Passkeys\" RENAME COLUMN \"CredentialId\" TO \"ItemId\";\n\nDROP INDEX IF EXISTS \"IX_Passkeys_CredentialId\";\n\nCREATE INDEX IF NOT EXISTS \"IX_Passkeys_ItemId\" ON \"Passkeys\" (\"ItemId\");\n\nALTER TABLE \"Attachments\" RENAME COLUMN \"CredentialId\" TO \"ItemId\";\n\nDROP INDEX IF EXISTS \"IX_Attachments_CredentialId\";\n\nCREATE INDEX IF NOT EXISTS \"IX_Attachments_ItemId\" ON \"Attachments\" (\"ItemId\");\n\nCREATE TABLE \"FieldDefinitions\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_FieldDefinitions\" PRIMARY KEY,\n \"FieldType\" TEXT NOT NULL,\n \"Label\" TEXT NOT NULL,\n \"IsMultiValue\" INTEGER NOT NULL,\n \"IsHidden\" INTEGER NOT NULL,\n \"EnableHistory\" INTEGER NOT NULL,\n \"Weight\" INTEGER NOT NULL,\n \"ApplicableToTypes\" TEXT NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"UpdatedAt\" TEXT NOT NULL,\n \"IsDeleted\" INTEGER NOT NULL\n);\n\nCREATE TABLE \"Folders\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_Folders\" PRIMARY KEY,\n \"Name\" TEXT NOT NULL,\n \"ParentFolderId\" TEXT NULL,\n \"Weight\" INTEGER NOT NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"UpdatedAt\" TEXT NOT NULL,\n \"IsDeleted\" INTEGER NOT NULL,\n CONSTRAINT \"FK_Folders_Folders_ParentFolderId\" FOREIGN KEY (\"ParentFolderId\") REFERENCES \"Folders\" (\"Id\") ON DELETE CASCADE\n);\n\nCREATE TABLE \"Logos\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_Logos\" PRIMARY KEY,\n \"Source\" TEXT NOT NULL,\n \"FileData\" BLOB NULL,\n \"MimeType\" TEXT NULL,\n \"FetchedAt\" TEXT NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"UpdatedAt\" TEXT NOT NULL,\n \"IsDeleted\" INTEGER NOT NULL\n);\n\nCREATE TABLE \"Tags\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_Tags\" PRIMARY KEY,\n \"Name\" TEXT NOT NULL,\n \"Color\" TEXT NULL,\n \"DisplayOrder\" INTEGER NOT NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"UpdatedAt\" TEXT NOT NULL,\n \"IsDeleted\" INTEGER NOT NULL\n);\n\nCREATE TABLE \"Items\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_Items\" PRIMARY KEY,\n \"Name\" TEXT NULL,\n \"ItemType\" TEXT NOT NULL,\n \"LogoId\" TEXT NULL,\n \"DeletedAt\" TEXT NULL,\n \"FolderId\" TEXT NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"UpdatedAt\" TEXT NOT NULL,\n \"IsDeleted\" INTEGER NOT NULL,\n CONSTRAINT \"FK_Items_Folders_FolderId\" FOREIGN KEY (\"FolderId\") REFERENCES \"Folders\" (\"Id\") ON DELETE SET NULL,\n CONSTRAINT \"FK_Items_Logos_LogoId\" FOREIGN KEY (\"LogoId\") REFERENCES \"Logos\" (\"Id\") ON DELETE SET NULL\n);\n\nCREATE TABLE \"FieldHistories\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_FieldHistories\" PRIMARY KEY,\n \"ItemId\" TEXT NOT NULL,\n \"FieldDefinitionId\" TEXT NULL,\n \"FieldKey\" TEXT NULL,\n \"ValueSnapshot\" TEXT NOT NULL,\n \"ChangedAt\" TEXT NOT NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"UpdatedAt\" TEXT NOT NULL,\n \"IsDeleted\" INTEGER NOT NULL,\n CONSTRAINT \"FK_FieldHistories_FieldDefinitions_FieldDefinitionId\" FOREIGN KEY (\"FieldDefinitionId\") REFERENCES \"FieldDefinitions\" (\"Id\") ON DELETE CASCADE,\n CONSTRAINT \"FK_FieldHistories_Items_ItemId\" FOREIGN KEY (\"ItemId\") REFERENCES \"Items\" (\"Id\") ON DELETE CASCADE\n);\n\nCREATE TABLE \"FieldValues\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_FieldValues\" PRIMARY KEY,\n \"ItemId\" TEXT NOT NULL,\n \"FieldDefinitionId\" TEXT NULL,\n \"FieldKey\" TEXT NULL,\n \"Value\" TEXT NULL,\n \"Weight\" INTEGER NOT NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"UpdatedAt\" TEXT NOT NULL,\n \"IsDeleted\" INTEGER NOT NULL,\n CONSTRAINT \"FK_FieldValues_FieldDefinitions_FieldDefinitionId\" FOREIGN KEY (\"FieldDefinitionId\") REFERENCES \"FieldDefinitions\" (\"Id\") ON DELETE CASCADE,\n CONSTRAINT \"FK_FieldValues_Items_ItemId\" FOREIGN KEY (\"ItemId\") REFERENCES \"Items\" (\"Id\") ON DELETE CASCADE\n);\n\nCREATE TABLE \"ItemTags\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_ItemTags\" PRIMARY KEY,\n \"ItemId\" TEXT NOT NULL,\n \"TagId\" TEXT NOT NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"UpdatedAt\" TEXT NOT NULL,\n \"IsDeleted\" INTEGER NOT NULL,\n CONSTRAINT \"FK_ItemTags_Items_ItemId\" FOREIGN KEY (\"ItemId\") REFERENCES \"Items\" (\"Id\") ON DELETE CASCADE,\n CONSTRAINT \"FK_ItemTags_Tags_TagId\" FOREIGN KEY (\"TagId\") REFERENCES \"Tags\" (\"Id\") ON DELETE CASCADE\n);\n\nCREATE INDEX \"IX_FieldHistories_FieldDefinitionId\" ON \"FieldHistories\" (\"FieldDefinitionId\");\n\nCREATE INDEX \"IX_FieldHistories_ItemId\" ON \"FieldHistories\" (\"ItemId\");\n\nCREATE INDEX \"IX_FieldValues_FieldDefinitionId\" ON \"FieldValues\" (\"FieldDefinitionId\");\n\nCREATE INDEX \"IX_FieldValues_FieldKey\" ON \"FieldValues\" (\"FieldKey\");\n\nCREATE INDEX \"IX_FieldValues_ItemId\" ON \"FieldValues\" (\"ItemId\");\n\nCREATE INDEX \"IX_FieldValues_ItemId_FieldDefinitionId_Weight\" ON \"FieldValues\" (\"ItemId\", \"FieldDefinitionId\", \"Weight\");\n\nCREATE INDEX \"IX_FieldValues_ItemId_FieldKey\" ON \"FieldValues\" (\"ItemId\", \"FieldKey\");\n\nCREATE INDEX \"IX_Folders_ParentFolderId\" ON \"Folders\" (\"ParentFolderId\");\n\nCREATE INDEX \"IX_Items_FolderId\" ON \"Items\" (\"FolderId\");\n\nCREATE INDEX \"IX_Items_LogoId\" ON \"Items\" (\"LogoId\");\n\nCREATE INDEX \"IX_ItemTags_ItemId\" ON \"ItemTags\" (\"ItemId\");\n\nCREATE UNIQUE INDEX \"IX_ItemTags_ItemId_TagId\" ON \"ItemTags\" (\"ItemId\", \"TagId\");\n\nCREATE INDEX \"IX_ItemTags_TagId\" ON \"ItemTags\" (\"TagId\");\n\nCREATE UNIQUE INDEX \"IX_Logos_Source\" ON \"Logos\" (\"Source\");\n\nCREATE INDEX \"IX_Tags_Name\" ON \"Tags\" (\"Name\");\n\n\n INSERT INTO Items (Id, Name, ItemType, LogoId, FolderId, CreatedAt, UpdatedAt, IsDeleted)\n SELECT\n c.Id,\n s.Name AS Name,\n CASE\n WHEN a.Id IS NOT NULL AND (\n (a.FirstName IS NOT NULL AND a.FirstName != '') OR\n (a.LastName IS NOT NULL AND a.LastName != '') OR\n (a.Gender IS NOT NULL AND a.Gender != '') OR\n (a.BirthDate IS NOT NULL AND a.BirthDate != '' AND a.BirthDate NOT LIKE '0001-%')\n ) THEN 'Alias'\n ELSE 'Login'\n END AS ItemType,\n NULL AS LogoId,\n NULL AS FolderId,\n c.CreatedAt,\n c.UpdatedAt,\n c.IsDeleted\n FROM Credentials c\n LEFT JOIN Services s ON s.Id = c.ServiceId\n LEFT JOIN Aliases a ON a.Id = c.AliasId;\n \n\n\n INSERT INTO Logos (Id, Source, FileData, MimeType, FetchedAt, CreatedAt, UpdatedAt, IsDeleted)\n SELECT\n UPPER(SUBSTR(hex(randomblob(4)), 1, 8) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(6)), 1, 12)) AS Id,\n -- Extract and normalize hostname: remove protocol, path, lowercase, and www. prefix\n REPLACE(\n LOWER(\n SUBSTR(\n CASE\n WHEN s.Url LIKE 'https://%' THEN SUBSTR(s.Url, 9)\n WHEN s.Url LIKE 'http://%' THEN SUBSTR(s.Url, 8)\n ELSE s.Url\n END,\n 1,\n CASE\n WHEN INSTR(\n CASE\n WHEN s.Url LIKE 'https://%' THEN SUBSTR(s.Url, 9)\n WHEN s.Url LIKE 'http://%' THEN SUBSTR(s.Url, 8)\n ELSE s.Url\n END, '/') > 0\n THEN INSTR(\n CASE\n WHEN s.Url LIKE 'https://%' THEN SUBSTR(s.Url, 9)\n WHEN s.Url LIKE 'http://%' THEN SUBSTR(s.Url, 8)\n ELSE s.Url\n END, '/') - 1\n ELSE LENGTH(\n CASE\n WHEN s.Url LIKE 'https://%' THEN SUBSTR(s.Url, 9)\n WHEN s.Url LIKE 'http://%' THEN SUBSTR(s.Url, 8)\n ELSE s.Url\n END)\n END\n )\n ),\n 'www.', ''\n ) AS Source,\n s.Logo AS FileData,\n 'image/png' AS MimeType,\n NULL AS FetchedAt,\n MIN(s.CreatedAt) AS CreatedAt,\n MAX(s.UpdatedAt) AS UpdatedAt,\n 0 AS IsDeleted\n FROM Services s\n WHERE s.Logo IS NOT NULL AND s.Url IS NOT NULL AND s.Url != ''\n GROUP BY REPLACE(\n LOWER(\n SUBSTR(\n CASE\n WHEN s.Url LIKE 'https://%' THEN SUBSTR(s.Url, 9)\n WHEN s.Url LIKE 'http://%' THEN SUBSTR(s.Url, 8)\n ELSE s.Url\n END,\n 1,\n CASE\n WHEN INSTR(\n CASE\n WHEN s.Url LIKE 'https://%' THEN SUBSTR(s.Url, 9)\n WHEN s.Url LIKE 'http://%' THEN SUBSTR(s.Url, 8)\n ELSE s.Url\n END, '/') > 0\n THEN INSTR(\n CASE\n WHEN s.Url LIKE 'https://%' THEN SUBSTR(s.Url, 9)\n WHEN s.Url LIKE 'http://%' THEN SUBSTR(s.Url, 8)\n ELSE s.Url\n END, '/') - 1\n ELSE LENGTH(\n CASE\n WHEN s.Url LIKE 'https://%' THEN SUBSTR(s.Url, 9)\n WHEN s.Url LIKE 'http://%' THEN SUBSTR(s.Url, 8)\n ELSE s.Url\n END)\n END\n )\n ),\n 'www.', ''\n );\n \n\n\n UPDATE Items\n SET LogoId = (\n SELECT l.Id FROM Logos l\n INNER JOIN Services s ON REPLACE(\n LOWER(\n SUBSTR(\n CASE\n WHEN s.Url LIKE 'https://%' THEN SUBSTR(s.Url, 9)\n WHEN s.Url LIKE 'http://%' THEN SUBSTR(s.Url, 8)\n ELSE s.Url\n END,\n 1,\n CASE\n WHEN INSTR(\n CASE\n WHEN s.Url LIKE 'https://%' THEN SUBSTR(s.Url, 9)\n WHEN s.Url LIKE 'http://%' THEN SUBSTR(s.Url, 8)\n ELSE s.Url\n END, '/') > 0\n THEN INSTR(\n CASE\n WHEN s.Url LIKE 'https://%' THEN SUBSTR(s.Url, 9)\n WHEN s.Url LIKE 'http://%' THEN SUBSTR(s.Url, 8)\n ELSE s.Url\n END, '/') - 1\n ELSE LENGTH(\n CASE\n WHEN s.Url LIKE 'https://%' THEN SUBSTR(s.Url, 9)\n WHEN s.Url LIKE 'http://%' THEN SUBSTR(s.Url, 8)\n ELSE s.Url\n END)\n END\n )\n ),\n 'www.', ''\n ) = l.Source\n INNER JOIN Credentials c ON c.ServiceId = s.Id\n WHERE c.Id = Items.Id\n LIMIT 1\n )\n WHERE EXISTS (\n SELECT 1 FROM Credentials c\n INNER JOIN Services s ON s.Id = c.ServiceId\n WHERE c.Id = Items.Id AND s.Logo IS NOT NULL\n );\n \n\n\n INSERT INTO FieldValues (Id, ItemId, FieldDefinitionId, FieldKey, Value, Weight, CreatedAt, UpdatedAt, IsDeleted)\n SELECT\n UPPER(SUBSTR(hex(randomblob(4)), 1, 8) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(6)), 1, 12)) AS Id,\n c.Id AS ItemId,\n NULL AS FieldDefinitionId,\n 'login.url' AS FieldKey,\n s.Url AS Value,\n 0 AS Weight,\n s.UpdatedAt AS CreatedAt,\n s.UpdatedAt AS UpdatedAt,\n 0 AS IsDeleted\n FROM Credentials c\n INNER JOIN Services s ON s.Id = c.ServiceId\n WHERE s.Url IS NOT NULL AND s.Url != '';\n \n\n\n INSERT INTO FieldValues (Id, ItemId, FieldDefinitionId, FieldKey, Value, Weight, CreatedAt, UpdatedAt, IsDeleted)\n SELECT\n UPPER(SUBSTR(hex(randomblob(4)), 1, 8) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(6)), 1, 12)) AS Id,\n c.Id AS ItemId,\n NULL AS FieldDefinitionId,\n 'login.username' AS FieldKey,\n c.Username AS Value,\n 0 AS Weight,\n c.UpdatedAt AS CreatedAt,\n c.UpdatedAt AS UpdatedAt,\n 0 AS IsDeleted\n FROM Credentials c\n WHERE c.Username IS NOT NULL AND c.Username != '';\n \n\n\n INSERT INTO FieldValues (Id, ItemId, FieldDefinitionId, FieldKey, Value, Weight, CreatedAt, UpdatedAt, IsDeleted)\n SELECT\n UPPER(SUBSTR(hex(randomblob(4)), 1, 8) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(6)), 1, 12)) AS Id,\n c.Id AS ItemId,\n NULL AS FieldDefinitionId,\n 'login.notes' AS FieldKey,\n c.Notes AS Value,\n 0 AS Weight,\n c.UpdatedAt AS CreatedAt,\n c.UpdatedAt AS UpdatedAt,\n 0 AS IsDeleted\n FROM Credentials c\n WHERE c.Notes IS NOT NULL AND c.Notes != '';\n \n\n\n INSERT INTO FieldValues (Id, ItemId, FieldDefinitionId, FieldKey, Value, Weight, CreatedAt, UpdatedAt, IsDeleted)\n SELECT\n UPPER(SUBSTR(hex(randomblob(4)), 1, 8) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(6)), 1, 12)) AS Id,\n p.CredentialId AS ItemId,\n NULL AS FieldDefinitionId,\n 'login.password' AS FieldKey,\n p.Value AS Value,\n 0 AS Weight,\n p.UpdatedAt AS CreatedAt,\n p.UpdatedAt AS UpdatedAt,\n 0 AS IsDeleted\n FROM Passwords p\n INNER JOIN (\n SELECT CredentialId, MAX(UpdatedAt) AS MaxUpdated, MAX(Id) AS MaxId\n FROM Passwords\n WHERE IsDeleted = 0\n GROUP BY CredentialId\n ) pm ON p.CredentialId = pm.CredentialId AND p.UpdatedAt = pm.MaxUpdated AND p.Id = pm.MaxId\n WHERE p.IsDeleted = 0;\n \n\n\n INSERT INTO FieldValues (Id, ItemId, FieldDefinitionId, FieldKey, Value, Weight, CreatedAt, UpdatedAt, IsDeleted)\n SELECT\n UPPER(SUBSTR(hex(randomblob(4)), 1, 8) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(6)), 1, 12)) AS Id,\n c.Id AS ItemId,\n NULL AS FieldDefinitionId,\n 'login.email' AS FieldKey,\n a.Email AS Value,\n 0 AS Weight,\n a.UpdatedAt AS CreatedAt,\n a.UpdatedAt AS UpdatedAt,\n 0 AS IsDeleted\n FROM Credentials c\n INNER JOIN Aliases a ON a.Id = c.AliasId\n WHERE a.Email IS NOT NULL AND a.Email != '';\n \n\n\n INSERT INTO FieldValues (Id, ItemId, FieldDefinitionId, FieldKey, Value, Weight, CreatedAt, UpdatedAt, IsDeleted)\n SELECT\n UPPER(SUBSTR(hex(randomblob(4)), 1, 8) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(6)), 1, 12)) AS Id,\n c.Id AS ItemId,\n NULL AS FieldDefinitionId,\n 'alias.first_name' AS FieldKey,\n a.FirstName AS Value,\n 0 AS Weight,\n a.UpdatedAt AS CreatedAt,\n a.UpdatedAt AS UpdatedAt,\n 0 AS IsDeleted\n FROM Credentials c\n INNER JOIN Aliases a ON a.Id = c.AliasId\n WHERE a.FirstName IS NOT NULL AND a.FirstName != '';\n \n\n\n INSERT INTO FieldValues (Id, ItemId, FieldDefinitionId, FieldKey, Value, Weight, CreatedAt, UpdatedAt, IsDeleted)\n SELECT\n UPPER(SUBSTR(hex(randomblob(4)), 1, 8) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(6)), 1, 12)) AS Id,\n c.Id AS ItemId,\n NULL AS FieldDefinitionId,\n 'alias.last_name' AS FieldKey,\n a.LastName AS Value,\n 0 AS Weight,\n a.UpdatedAt AS CreatedAt,\n a.UpdatedAt AS UpdatedAt,\n 0 AS IsDeleted\n FROM Credentials c\n INNER JOIN Aliases a ON a.Id = c.AliasId\n WHERE a.LastName IS NOT NULL AND a.LastName != '';\n \n\n\n INSERT INTO FieldValues (Id, ItemId, FieldDefinitionId, FieldKey, Value, Weight, CreatedAt, UpdatedAt, IsDeleted)\n SELECT\n UPPER(SUBSTR(hex(randomblob(4)), 1, 8) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(6)), 1, 12)) AS Id,\n c.Id AS ItemId,\n NULL AS FieldDefinitionId,\n 'alias.gender' AS FieldKey,\n a.Gender AS Value,\n 0 AS Weight,\n a.UpdatedAt AS CreatedAt,\n a.UpdatedAt AS UpdatedAt,\n 0 AS IsDeleted\n FROM Credentials c\n INNER JOIN Aliases a ON a.Id = c.AliasId\n WHERE a.Gender IS NOT NULL AND a.Gender != '';\n \n\n\n INSERT INTO FieldValues (Id, ItemId, FieldDefinitionId, FieldKey, Value, Weight, CreatedAt, UpdatedAt, IsDeleted)\n SELECT\n UPPER(SUBSTR(hex(randomblob(4)), 1, 8) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(6)), 1, 12)) AS Id,\n c.Id AS ItemId,\n NULL AS FieldDefinitionId,\n 'alias.birthdate' AS FieldKey,\n SUBSTR(a.BirthDate, 1, 10) AS Value,\n 0 AS Weight,\n a.UpdatedAt AS CreatedAt,\n a.UpdatedAt AS UpdatedAt,\n 0 AS IsDeleted\n FROM Credentials c\n INNER JOIN Aliases a ON a.Id = c.AliasId\n WHERE a.BirthDate IS NOT NULL AND a.BirthDate != '' AND a.BirthDate NOT LIKE '0001-%';\n \n\nDROP TABLE \"Passwords\";\n\nDROP TABLE \"Credentials\";\n\nDROP TABLE \"Aliases\";\n\nDROP TABLE \"Services\";\n\nCREATE TABLE \"ef_temp_Attachments\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_Attachments\" PRIMARY KEY,\n \"Blob\" BLOB NOT NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"Filename\" TEXT NOT NULL,\n \"IsDeleted\" INTEGER NOT NULL,\n \"ItemId\" TEXT NOT NULL,\n \"UpdatedAt\" TEXT NOT NULL,\n CONSTRAINT \"FK_Attachments_Items_ItemId\" FOREIGN KEY (\"ItemId\") REFERENCES \"Items\" (\"Id\") ON DELETE CASCADE\n);\n\nINSERT INTO \"ef_temp_Attachments\" (\"Id\", \"Blob\", \"CreatedAt\", \"Filename\", \"IsDeleted\", \"ItemId\", \"UpdatedAt\")\nSELECT \"Id\", \"Blob\", \"CreatedAt\", \"Filename\", \"IsDeleted\", \"ItemId\", \"UpdatedAt\"\nFROM \"Attachments\";\n\nCREATE TABLE \"ef_temp_Passkeys\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_Passkeys\" PRIMARY KEY,\n \"AdditionalData\" BLOB NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"DisplayName\" TEXT NOT NULL,\n \"IsDeleted\" INTEGER NOT NULL,\n \"ItemId\" TEXT NOT NULL,\n \"PrfKey\" BLOB NULL,\n \"PrivateKey\" TEXT NOT NULL,\n \"PublicKey\" TEXT NOT NULL,\n \"RpId\" TEXT COLLATE NOCASE NOT NULL,\n \"UpdatedAt\" TEXT NOT NULL,\n \"UserHandle\" BLOB NOT NULL,\n CONSTRAINT \"FK_Passkeys_Items_ItemId\" FOREIGN KEY (\"ItemId\") REFERENCES \"Items\" (\"Id\") ON DELETE CASCADE\n);\n\nINSERT INTO \"ef_temp_Passkeys\" (\"Id\", \"AdditionalData\", \"CreatedAt\", \"DisplayName\", \"IsDeleted\", \"ItemId\", \"PrfKey\", \"PrivateKey\", \"PublicKey\", \"RpId\", \"UpdatedAt\", \"UserHandle\")\nSELECT \"Id\", \"AdditionalData\", \"CreatedAt\", \"DisplayName\", \"IsDeleted\", \"ItemId\", \"PrfKey\", \"PrivateKey\", \"PublicKey\", \"RpId\", \"UpdatedAt\", \"UserHandle\"\nFROM \"Passkeys\";\n\nCREATE TABLE \"ef_temp_TotpCodes\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_TotpCodes\" PRIMARY KEY,\n \"CreatedAt\" TEXT NOT NULL,\n \"IsDeleted\" INTEGER NOT NULL,\n \"ItemId\" TEXT NOT NULL,\n \"Name\" TEXT NOT NULL,\n \"SecretKey\" TEXT NOT NULL,\n \"UpdatedAt\" TEXT NOT NULL,\n CONSTRAINT \"FK_TotpCodes_Items_ItemId\" FOREIGN KEY (\"ItemId\") REFERENCES \"Items\" (\"Id\") ON DELETE CASCADE\n);\n\nINSERT INTO \"ef_temp_TotpCodes\" (\"Id\", \"CreatedAt\", \"IsDeleted\", \"ItemId\", \"Name\", \"SecretKey\", \"UpdatedAt\")\nSELECT \"Id\", \"CreatedAt\", \"IsDeleted\", \"ItemId\", \"Name\", \"SecretKey\", \"UpdatedAt\"\nFROM \"TotpCodes\";\n\nCOMMIT;\n\nPRAGMA foreign_keys = 0;\n\nBEGIN TRANSACTION;\nDROP TABLE \"Attachments\";\n\nALTER TABLE \"ef_temp_Attachments\" RENAME TO \"Attachments\";\n\nDROP TABLE \"Passkeys\";\n\nALTER TABLE \"ef_temp_Passkeys\" RENAME TO \"Passkeys\";\n\nDROP TABLE \"TotpCodes\";\n\nALTER TABLE \"ef_temp_TotpCodes\" RENAME TO \"TotpCodes\";\n\nCOMMIT;\n\nPRAGMA foreign_keys = 1;\n\nBEGIN TRANSACTION;\nCREATE INDEX \"IX_Attachments_ItemId\" ON \"Attachments\" (\"ItemId\");\n\nCREATE INDEX \"IX_Passkeys_ItemId\" ON \"Passkeys\" (\"ItemId\");\n\nCREATE INDEX \"IX_Passkeys_RpId\" ON \"Passkeys\" (\"RpId\");\n\nCREATE INDEX \"IX_TotpCodes_ItemId\" ON \"TotpCodes\" (\"ItemId\");\n\nCOMMIT;\n\nINSERT INTO \"__EFMigrationsHistory\" (\"MigrationId\", \"ProductVersion\")\nVALUES ('20251213111207_1.7.0-FieldBasedDataModelUpdate', '9.0.4');\n"; +declare const COMPLETE_SCHEMA_SQL = "\n\uFEFFCREATE TABLE IF NOT EXISTS \"__EFMigrationsHistory\" (\n \"MigrationId\" TEXT NOT NULL CONSTRAINT \"PK___EFMigrationsHistory\" PRIMARY KEY,\n \"ProductVersion\" TEXT NOT NULL\n);\n\nBEGIN TRANSACTION;\nCREATE TABLE \"Aliases\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_Aliases\" PRIMARY KEY,\n \"Gender\" VARCHAR NULL,\n \"FirstName\" VARCHAR NULL,\n \"LastName\" VARCHAR NULL,\n \"NickName\" VARCHAR NULL,\n \"BirthDate\" TEXT NOT NULL,\n \"AddressStreet\" VARCHAR NULL,\n \"AddressCity\" VARCHAR NULL,\n \"AddressState\" VARCHAR NULL,\n \"AddressZipCode\" VARCHAR NULL,\n \"AddressCountry\" VARCHAR NULL,\n \"Hobbies\" TEXT NULL,\n \"EmailPrefix\" TEXT NULL,\n \"PhoneMobile\" TEXT NULL,\n \"BankAccountIBAN\" TEXT NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"UpdatedAt\" TEXT NOT NULL\n);\n\nCREATE TABLE \"Services\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_Services\" PRIMARY KEY,\n \"Name\" TEXT NULL,\n \"Url\" TEXT NULL,\n \"Logo\" BLOB NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"UpdatedAt\" TEXT NOT NULL\n);\n\nCREATE TABLE \"Credentials\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_Credentials\" PRIMARY KEY,\n \"AliasId\" TEXT NOT NULL,\n \"Notes\" TEXT NULL,\n \"Username\" TEXT NOT NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"UpdatedAt\" TEXT NOT NULL,\n \"ServiceId\" TEXT NOT NULL,\n CONSTRAINT \"FK_Credentials_Aliases_AliasId\" FOREIGN KEY (\"AliasId\") REFERENCES \"Aliases\" (\"Id\") ON DELETE CASCADE,\n CONSTRAINT \"FK_Credentials_Services_ServiceId\" FOREIGN KEY (\"ServiceId\") REFERENCES \"Services\" (\"Id\") ON DELETE CASCADE\n);\n\nCREATE TABLE \"Attachment\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_Attachment\" PRIMARY KEY,\n \"Filename\" TEXT NOT NULL,\n \"Blob\" BLOB NOT NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"UpdatedAt\" TEXT NOT NULL,\n \"CredentialId\" TEXT NOT NULL,\n CONSTRAINT \"FK_Attachment_Credentials_CredentialId\" FOREIGN KEY (\"CredentialId\") REFERENCES \"Credentials\" (\"Id\") ON DELETE CASCADE\n);\n\nCREATE TABLE \"Passwords\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_Passwords\" PRIMARY KEY,\n \"Value\" TEXT NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"UpdatedAt\" TEXT NOT NULL,\n \"CredentialId\" TEXT NOT NULL,\n CONSTRAINT \"FK_Passwords_Credentials_CredentialId\" FOREIGN KEY (\"CredentialId\") REFERENCES \"Credentials\" (\"Id\") ON DELETE CASCADE\n);\n\nCREATE INDEX \"IX_Attachment_CredentialId\" ON \"Attachment\" (\"CredentialId\");\n\nCREATE INDEX \"IX_Credentials_AliasId\" ON \"Credentials\" (\"AliasId\");\n\nCREATE INDEX \"IX_Credentials_ServiceId\" ON \"Credentials\" (\"ServiceId\");\n\nCREATE INDEX \"IX_Passwords_CredentialId\" ON \"Passwords\" (\"CredentialId\");\n\nINSERT INTO \"__EFMigrationsHistory\" (\"MigrationId\", \"ProductVersion\")\nVALUES ('20240708094944_1.0.0-InitialMigration', '9.0.4');\n\nINSERT INTO \"__EFMigrationsHistory\" (\"MigrationId\", \"ProductVersion\")\nVALUES ('20240708224522_1.0.1-EmptyTestMigration', '9.0.4');\n\nALTER TABLE \"Aliases\" RENAME COLUMN \"EmailPrefix\" TO \"Email\";\n\nINSERT INTO \"__EFMigrationsHistory\" (\"MigrationId\", \"ProductVersion\")\nVALUES ('20240711204207_1.0.2-ChangeEmailColumn', '9.0.4');\n\nCREATE TABLE \"EncryptionKeys\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_EncryptionKeys\" PRIMARY KEY,\n \"PublicKey\" TEXT NOT NULL,\n \"PrivateKey\" TEXT NOT NULL,\n \"IsPrimary\" INTEGER NOT NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"UpdatedAt\" TEXT NOT NULL\n);\n\nINSERT INTO \"__EFMigrationsHistory\" (\"MigrationId\", \"ProductVersion\")\nVALUES ('20240729105618_1.1.0-AddPkiTables', '9.0.4');\n\nCREATE TABLE \"Settings\" (\n \"Key\" TEXT NOT NULL CONSTRAINT \"PK_Settings\" PRIMARY KEY,\n \"Value\" TEXT NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"UpdatedAt\" TEXT NOT NULL\n);\n\nINSERT INTO \"__EFMigrationsHistory\" (\"MigrationId\", \"ProductVersion\")\nVALUES ('20240805073413_1.2.0-AddSettingsTable', '9.0.4');\n\nCREATE TABLE \"ef_temp_Aliases\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_Aliases\" PRIMARY KEY,\n \"BirthDate\" TEXT NOT NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"Email\" TEXT NULL,\n \"FirstName\" VARCHAR NULL,\n \"Gender\" VARCHAR NULL,\n \"LastName\" VARCHAR NULL,\n \"NickName\" VARCHAR NULL,\n \"UpdatedAt\" TEXT NOT NULL\n);\n\nINSERT INTO \"ef_temp_Aliases\" (\"Id\", \"BirthDate\", \"CreatedAt\", \"Email\", \"FirstName\", \"Gender\", \"LastName\", \"NickName\", \"UpdatedAt\")\nSELECT \"Id\", \"BirthDate\", \"CreatedAt\", \"Email\", \"FirstName\", \"Gender\", \"LastName\", \"NickName\", \"UpdatedAt\"\nFROM \"Aliases\";\n\nCOMMIT;\n\nPRAGMA foreign_keys = 0;\n\nBEGIN TRANSACTION;\nDROP TABLE \"Aliases\";\n\nALTER TABLE \"ef_temp_Aliases\" RENAME TO \"Aliases\";\n\nCOMMIT;\n\nPRAGMA foreign_keys = 1;\n\nINSERT INTO \"__EFMigrationsHistory\" (\"MigrationId\", \"ProductVersion\")\nVALUES ('20240805122422_1.3.0-UpdateIdentityStructure', '9.0.4');\n\nBEGIN TRANSACTION;\nCREATE TABLE \"ef_temp_Credentials\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_Credentials\" PRIMARY KEY,\n \"AliasId\" TEXT NOT NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"Notes\" TEXT NULL,\n \"ServiceId\" TEXT NOT NULL,\n \"UpdatedAt\" TEXT NOT NULL,\n \"Username\" TEXT NULL,\n CONSTRAINT \"FK_Credentials_Aliases_AliasId\" FOREIGN KEY (\"AliasId\") REFERENCES \"Aliases\" (\"Id\") ON DELETE CASCADE,\n CONSTRAINT \"FK_Credentials_Services_ServiceId\" FOREIGN KEY (\"ServiceId\") REFERENCES \"Services\" (\"Id\") ON DELETE CASCADE\n);\n\nINSERT INTO \"ef_temp_Credentials\" (\"Id\", \"AliasId\", \"CreatedAt\", \"Notes\", \"ServiceId\", \"UpdatedAt\", \"Username\")\nSELECT \"Id\", \"AliasId\", \"CreatedAt\", \"Notes\", \"ServiceId\", \"UpdatedAt\", \"Username\"\nFROM \"Credentials\";\n\nCOMMIT;\n\nPRAGMA foreign_keys = 0;\n\nBEGIN TRANSACTION;\nDROP TABLE \"Credentials\";\n\nALTER TABLE \"ef_temp_Credentials\" RENAME TO \"Credentials\";\n\nCOMMIT;\n\nPRAGMA foreign_keys = 1;\n\nBEGIN TRANSACTION;\nCREATE INDEX \"IX_Credentials_AliasId\" ON \"Credentials\" (\"AliasId\");\n\nCREATE INDEX \"IX_Credentials_ServiceId\" ON \"Credentials\" (\"ServiceId\");\n\nCOMMIT;\n\nINSERT INTO \"__EFMigrationsHistory\" (\"MigrationId\", \"ProductVersion\")\nVALUES ('20240812141727_1.3.1-MakeUsernameOptional', '9.0.4');\n\nBEGIN TRANSACTION;\nALTER TABLE \"Settings\" ADD \"IsDeleted\" INTEGER NOT NULL DEFAULT 0;\n\nALTER TABLE \"Services\" ADD \"IsDeleted\" INTEGER NOT NULL DEFAULT 0;\n\nALTER TABLE \"Passwords\" ADD \"IsDeleted\" INTEGER NOT NULL DEFAULT 0;\n\nALTER TABLE \"EncryptionKeys\" ADD \"IsDeleted\" INTEGER NOT NULL DEFAULT 0;\n\nALTER TABLE \"Credentials\" ADD \"IsDeleted\" INTEGER NOT NULL DEFAULT 0;\n\nALTER TABLE \"Attachment\" ADD \"IsDeleted\" INTEGER NOT NULL DEFAULT 0;\n\nALTER TABLE \"Aliases\" ADD \"IsDeleted\" INTEGER NOT NULL DEFAULT 0;\n\nINSERT INTO \"__EFMigrationsHistory\" (\"MigrationId\", \"ProductVersion\")\nVALUES ('20240916105320_1.4.0-AddSyncSupport', '9.0.4');\n\nALTER TABLE \"Attachment\" RENAME TO \"Attachments\";\n\nCREATE TABLE \"ef_temp_Attachments\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_Attachments\" PRIMARY KEY,\n \"Blob\" BLOB NOT NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"CredentialId\" TEXT NOT NULL,\n \"Filename\" TEXT NOT NULL,\n \"IsDeleted\" INTEGER NOT NULL,\n \"UpdatedAt\" TEXT NOT NULL,\n CONSTRAINT \"FK_Attachments_Credentials_CredentialId\" FOREIGN KEY (\"CredentialId\") REFERENCES \"Credentials\" (\"Id\") ON DELETE CASCADE\n);\n\nINSERT INTO \"ef_temp_Attachments\" (\"Id\", \"Blob\", \"CreatedAt\", \"CredentialId\", \"Filename\", \"IsDeleted\", \"UpdatedAt\")\nSELECT \"Id\", \"Blob\", \"CreatedAt\", \"CredentialId\", \"Filename\", \"IsDeleted\", \"UpdatedAt\"\nFROM \"Attachments\";\n\nCOMMIT;\n\nPRAGMA foreign_keys = 0;\n\nBEGIN TRANSACTION;\nDROP TABLE \"Attachments\";\n\nALTER TABLE \"ef_temp_Attachments\" RENAME TO \"Attachments\";\n\nCOMMIT;\n\nPRAGMA foreign_keys = 1;\n\nBEGIN TRANSACTION;\nCREATE INDEX \"IX_Attachments_CredentialId\" ON \"Attachments\" (\"CredentialId\");\n\nCOMMIT;\n\nINSERT INTO \"__EFMigrationsHistory\" (\"MigrationId\", \"ProductVersion\")\nVALUES ('20240917191243_1.4.1-RenameAttachmentsPlural', '9.0.4');\n\nBEGIN TRANSACTION;\nCREATE TABLE \"TotpCodes\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_TotpCodes\" PRIMARY KEY,\n \"Name\" TEXT NOT NULL,\n \"SecretKey\" TEXT NOT NULL,\n \"CredentialId\" TEXT NOT NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"UpdatedAt\" TEXT NOT NULL,\n \"IsDeleted\" INTEGER NOT NULL,\n CONSTRAINT \"FK_TotpCodes_Credentials_CredentialId\" FOREIGN KEY (\"CredentialId\") REFERENCES \"Credentials\" (\"Id\") ON DELETE CASCADE\n);\n\nCREATE INDEX \"IX_TotpCodes_CredentialId\" ON \"TotpCodes\" (\"CredentialId\");\n\nINSERT INTO \"__EFMigrationsHistory\" (\"MigrationId\", \"ProductVersion\")\nVALUES ('20250310131554_1.5.0-AddTotpCodes', '9.0.4');\n\n\nPRAGMA foreign_keys = OFF;\n\n-- Clean up any existing temp tables first\nDROP TABLE IF EXISTS \"__EFMigrationsHistory_temp\";\nDROP TABLE IF EXISTS \"Aliases_temp\";\nDROP TABLE IF EXISTS \"Services_temp\";\nDROP TABLE IF EXISTS \"EncryptionKeys_temp\";\nDROP TABLE IF EXISTS \"Settings_temp\";\nDROP TABLE IF EXISTS \"Credentials_temp\";\nDROP TABLE IF EXISTS \"Attachments_temp\";\nDROP TABLE IF EXISTS \"Passwords_temp\";\nDROP TABLE IF EXISTS \"TotpCodes_temp\";\n\n-- Create backup tables for all data\nCREATE TABLE \"__EFMigrationsHistory_temp\" AS SELECT * FROM \"__EFMigrationsHistory\";\nCREATE TABLE \"Aliases_temp\" AS SELECT * FROM \"Aliases\";\nCREATE TABLE \"Services_temp\" AS SELECT * FROM \"Services\";\nCREATE TABLE \"EncryptionKeys_temp\" AS SELECT * FROM \"EncryptionKeys\";\nCREATE TABLE \"Settings_temp\" AS SELECT * FROM \"Settings\";\nCREATE TABLE \"Credentials_temp\" AS SELECT * FROM \"Credentials\";\nCREATE TABLE \"Attachments_temp\" AS SELECT * FROM \"Attachments\";\nCREATE TABLE \"Passwords_temp\" AS SELECT * FROM \"Passwords\";\nCREATE TABLE \"TotpCodes_temp\" AS SELECT * FROM \"TotpCodes\";\n\n-- Delete orphaned records that do not have a valid FK to the credential object\nDELETE FROM \"Attachments_temp\" WHERE \"CredentialId\" NOT IN (SELECT \"Id\" FROM \"Credentials_temp\");\nDELETE FROM \"Passwords_temp\" WHERE \"CredentialId\" NOT IN (SELECT \"Id\" FROM \"Credentials_temp\");\nDELETE FROM \"TotpCodes_temp\" WHERE \"CredentialId\" NOT IN (SELECT \"Id\" FROM \"Credentials_temp\");\n\n-- Delete orphaned credentials that do not have valid FKs to alias or service objects\nDELETE FROM \"Credentials_temp\" WHERE \"AliasId\" NOT IN (SELECT \"Id\" FROM \"Aliases_temp\");\nDELETE FROM \"Credentials_temp\" WHERE \"ServiceId\" NOT IN (SELECT \"Id\" FROM \"Services_temp\");\n\n-- After cleaning credentials, clean dependent tables again in case we removed credentials\nDELETE FROM \"Attachments_temp\" WHERE \"CredentialId\" NOT IN (SELECT \"Id\" FROM \"Credentials_temp\");\nDELETE FROM \"Passwords_temp\" WHERE \"CredentialId\" NOT IN (SELECT \"Id\" FROM \"Credentials_temp\");\nDELETE FROM \"TotpCodes_temp\" WHERE \"CredentialId\" NOT IN (SELECT \"Id\" FROM \"Credentials_temp\");\n\n-- Drop all existing tables\nDROP TABLE \"TotpCodes\";\nDROP TABLE \"Passwords\";\nDROP TABLE \"Attachments\";\nDROP TABLE \"Credentials\";\nDROP TABLE \"Settings\";\nDROP TABLE \"EncryptionKeys\";\nDROP TABLE \"Services\";\nDROP TABLE \"Aliases\";\nDROP TABLE \"__EFMigrationsHistory\";\n\n-- Recreate tables with proper constraints (no dependencies first)\nCREATE TABLE \"__EFMigrationsHistory\" (\n \"MigrationId\" TEXT NOT NULL CONSTRAINT \"PK___EFMigrationsHistory\" PRIMARY KEY,\n \"ProductVersion\" TEXT NOT NULL\n);\n\nCREATE TABLE \"Aliases\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_Aliases\" PRIMARY KEY,\n \"BirthDate\" TEXT NOT NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"Email\" TEXT NULL,\n \"FirstName\" VARCHAR NULL,\n \"Gender\" VARCHAR NULL,\n \"LastName\" VARCHAR NULL,\n \"NickName\" VARCHAR NULL,\n \"UpdatedAt\" TEXT NOT NULL,\n \"IsDeleted\" INTEGER NOT NULL DEFAULT 0\n);\n\nCREATE TABLE \"Services\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_Services\" PRIMARY KEY,\n \"Name\" TEXT NULL,\n \"Url\" TEXT NULL,\n \"Logo\" BLOB NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"UpdatedAt\" TEXT NOT NULL,\n \"IsDeleted\" INTEGER NOT NULL DEFAULT 0\n);\n\nCREATE TABLE \"EncryptionKeys\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_EncryptionKeys\" PRIMARY KEY,\n \"PublicKey\" TEXT NOT NULL,\n \"PrivateKey\" TEXT NOT NULL,\n \"IsPrimary\" INTEGER NOT NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"UpdatedAt\" TEXT NOT NULL,\n \"IsDeleted\" INTEGER NOT NULL DEFAULT 0\n);\n\nCREATE TABLE \"Settings\" (\n \"Key\" TEXT NOT NULL CONSTRAINT \"PK_Settings\" PRIMARY KEY,\n \"Value\" TEXT NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"UpdatedAt\" TEXT NOT NULL,\n \"IsDeleted\" INTEGER NOT NULL DEFAULT 0\n);\n\n-- Tables with foreign keys\nCREATE TABLE \"Credentials\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_Credentials\" PRIMARY KEY,\n \"AliasId\" TEXT NOT NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"Notes\" TEXT NULL,\n \"ServiceId\" TEXT NOT NULL,\n \"UpdatedAt\" TEXT NOT NULL,\n \"Username\" TEXT NULL,\n \"IsDeleted\" INTEGER NOT NULL DEFAULT 0,\n CONSTRAINT \"FK_Credentials_Aliases_AliasId\" FOREIGN KEY (\"AliasId\") REFERENCES \"Aliases\" (\"Id\") ON DELETE CASCADE,\n CONSTRAINT \"FK_Credentials_Services_ServiceId\" FOREIGN KEY (\"ServiceId\") REFERENCES \"Services\" (\"Id\") ON DELETE CASCADE\n);\n\nCREATE TABLE \"Attachments\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_Attachments\" PRIMARY KEY,\n \"Blob\" BLOB NOT NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"CredentialId\" TEXT NOT NULL,\n \"Filename\" TEXT NOT NULL,\n \"IsDeleted\" INTEGER NOT NULL DEFAULT 0,\n \"UpdatedAt\" TEXT NOT NULL,\n CONSTRAINT \"FK_Attachments_Credentials_CredentialId\" FOREIGN KEY (\"CredentialId\") REFERENCES \"Credentials\" (\"Id\") ON DELETE CASCADE\n);\n\nCREATE TABLE \"Passwords\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_Passwords\" PRIMARY KEY,\n \"Value\" TEXT NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"UpdatedAt\" TEXT NOT NULL,\n \"CredentialId\" TEXT NOT NULL,\n \"IsDeleted\" INTEGER NOT NULL DEFAULT 0,\n CONSTRAINT \"FK_Passwords_Credentials_CredentialId\" FOREIGN KEY (\"CredentialId\") REFERENCES \"Credentials\" (\"Id\") ON DELETE CASCADE\n);\n\nCREATE TABLE \"TotpCodes\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_TotpCodes\" PRIMARY KEY,\n \"Name\" TEXT NOT NULL,\n \"SecretKey\" TEXT NOT NULL,\n \"CredentialId\" TEXT NOT NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"UpdatedAt\" TEXT NOT NULL,\n \"IsDeleted\" INTEGER NOT NULL DEFAULT 0,\n CONSTRAINT \"FK_TotpCodes_Credentials_CredentialId\" FOREIGN KEY (\"CredentialId\") REFERENCES \"Credentials\" (\"Id\") ON DELETE CASCADE\n);\n\n\n-- Restore data from temp tables\nINSERT INTO \"__EFMigrationsHistory\" SELECT * FROM \"__EFMigrationsHistory_temp\";\nINSERT INTO \"Aliases\" SELECT * FROM \"Aliases_temp\";\nINSERT INTO \"Services\" SELECT * FROM \"Services_temp\";\nINSERT INTO \"EncryptionKeys\" SELECT * FROM \"EncryptionKeys_temp\";\nINSERT INTO \"Settings\" SELECT * FROM \"Settings_temp\";\nINSERT INTO \"Credentials\" SELECT * FROM \"Credentials_temp\";\nINSERT INTO \"Attachments\" SELECT * FROM \"Attachments_temp\";\nINSERT INTO \"Passwords\" SELECT * FROM \"Passwords_temp\";\nINSERT INTO \"TotpCodes\" SELECT * FROM \"TotpCodes_temp\";\n\n-- =====================================================================================\n-- Date Format Normalization Migration\n-- =====================================================================================\n-- This migration normalizes ALL date fields to the standard format: 'yyyy-MM-dd HH:mm:ss.fff'\n-- Previously the different clients used different date formats which complicate date parsing.\n-- From version 0.24.0 onwards, all new dates are stored in this standard format.\n\n-- Update Aliases table (CreatedAt, UpdatedAt, BirthDate)\nUPDATE \"Aliases\" SET \"CreatedAt\" =\n CASE\n -- Already in correct format (yyyy-MM-dd HH:mm:ss.fff) - no change\n WHEN \"CreatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9] [0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9][0-9][0-9]'\n THEN \"CreatedAt\"\n\n -- ISO 8601 with milliseconds (yyyy-MM-ddTHH:mm:ss.fffZ) -> Replace T with space, remove Z and everything after .fff\n WHEN \"CreatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]T[0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9]*'\n THEN substr(\"CreatedAt\", 1, 10) || ' ' || substr(\"CreatedAt\", 12, 12)\n\n -- Without milliseconds (yyyy-MM-dd HH:mm:ss or yyyy-MM-ddTHH:mm:ssZ) -> Add .000\n WHEN \"CreatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9][T ][0-9][0-9]:[0-9][0-9]:[0-9][0-9]*'\n THEN substr(\"CreatedAt\", 1, 10) || ' ' || substr(replace(\"CreatedAt\", 'T', ' '), 12, 8) || '.000'\n\n -- Fallback: if none match, keep as-is (edge case)\n ELSE \"CreatedAt\"\n END;\n\nUPDATE \"Aliases\" SET \"UpdatedAt\" =\n CASE\n WHEN \"UpdatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9] [0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9][0-9][0-9]'\n THEN \"UpdatedAt\"\n WHEN \"UpdatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]T[0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9]*'\n THEN substr(\"UpdatedAt\", 1, 10) || ' ' || substr(\"UpdatedAt\", 12, 12)\n WHEN \"UpdatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9][T ][0-9][0-9]:[0-9][0-9]:[0-9][0-9]*'\n THEN substr(\"UpdatedAt\", 1, 10) || ' ' || substr(replace(\"UpdatedAt\", 'T', ' '), 12, 8) || '.000'\n ELSE \"UpdatedAt\"\n END;\n\n-- BirthDate: Always set time to 00:00:00 (no milliseconds for birth dates)\nUPDATE \"Aliases\" SET \"BirthDate\" =\n CASE\n -- If empty or already '0001-01-01 00:00:00', keep as-is\n WHEN \"BirthDate\" = '' OR \"BirthDate\" = '0001-01-01 00:00:00'\n THEN \"BirthDate\"\n\n -- If already in correct format (yyyy-MM-dd 00:00:00), keep as-is\n WHEN \"BirthDate\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9] 00:00:00'\n THEN \"BirthDate\"\n\n -- Extract date part and set time to 00:00:00\n WHEN \"BirthDate\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]*'\n THEN substr(\"BirthDate\", 1, 10) || ' 00:00:00'\n\n -- Fallback\n ELSE \"BirthDate\"\n END;\n\n-- Update Services table (CreatedAt, UpdatedAt)\nUPDATE \"Services\" SET \"CreatedAt\" =\n CASE\n WHEN \"CreatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9] [0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9][0-9][0-9]'\n THEN \"CreatedAt\"\n WHEN \"CreatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]T[0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9]*'\n THEN substr(\"CreatedAt\", 1, 10) || ' ' || substr(\"CreatedAt\", 12, 12)\n WHEN \"CreatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9][T ][0-9][0-9]:[0-9][0-9]:[0-9][0-9]*'\n THEN substr(\"CreatedAt\", 1, 10) || ' ' || substr(replace(\"CreatedAt\", 'T', ' '), 12, 8) || '.000'\n ELSE \"CreatedAt\"\n END;\n\nUPDATE \"Services\" SET \"UpdatedAt\" =\n CASE\n WHEN \"UpdatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9] [0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9][0-9][0-9]'\n THEN \"UpdatedAt\"\n WHEN \"UpdatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]T[0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9]*'\n THEN substr(\"UpdatedAt\", 1, 10) || ' ' || substr(\"UpdatedAt\", 12, 12)\n WHEN \"UpdatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9][T ][0-9][0-9]:[0-9][0-9]:[0-9][0-9]*'\n THEN substr(\"UpdatedAt\", 1, 10) || ' ' || substr(replace(\"UpdatedAt\", 'T', ' '), 12, 8) || '.000'\n ELSE \"UpdatedAt\"\n END;\n\n-- Update EncryptionKeys table (CreatedAt, UpdatedAt)\nUPDATE \"EncryptionKeys\" SET \"CreatedAt\" =\n CASE\n WHEN \"CreatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9] [0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9][0-9][0-9]'\n THEN \"CreatedAt\"\n WHEN \"CreatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]T[0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9]*'\n THEN substr(\"CreatedAt\", 1, 10) || ' ' || substr(\"CreatedAt\", 12, 12)\n WHEN \"CreatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9][T ][0-9][0-9]:[0-9][0-9]:[0-9][0-9]*'\n THEN substr(\"CreatedAt\", 1, 10) || ' ' || substr(replace(\"CreatedAt\", 'T', ' '), 12, 8) || '.000'\n ELSE \"CreatedAt\"\n END;\n\nUPDATE \"EncryptionKeys\" SET \"UpdatedAt\" =\n CASE\n WHEN \"UpdatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9] [0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9][0-9][0-9]'\n THEN \"UpdatedAt\"\n WHEN \"UpdatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]T[0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9]*'\n THEN substr(\"UpdatedAt\", 1, 10) || ' ' || substr(\"UpdatedAt\", 12, 12)\n WHEN \"UpdatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9][T ][0-9][0-9]:[0-9][0-9]:[0-9][0-9]*'\n THEN substr(\"UpdatedAt\", 1, 10) || ' ' || substr(replace(\"UpdatedAt\", 'T', ' '), 12, 8) || '.000'\n ELSE \"UpdatedAt\"\n END;\n\n-- Update Settings table (CreatedAt, UpdatedAt)\nUPDATE \"Settings\" SET \"CreatedAt\" =\n CASE\n WHEN \"CreatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9] [0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9][0-9][0-9]'\n THEN \"CreatedAt\"\n WHEN \"CreatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]T[0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9]*'\n THEN substr(\"CreatedAt\", 1, 10) || ' ' || substr(\"CreatedAt\", 12, 12)\n WHEN \"CreatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9][T ][0-9][0-9]:[0-9][0-9]:[0-9][0-9]*'\n THEN substr(\"CreatedAt\", 1, 10) || ' ' || substr(replace(\"CreatedAt\", 'T', ' '), 12, 8) || '.000'\n ELSE \"CreatedAt\"\n END;\n\nUPDATE \"Settings\" SET \"UpdatedAt\" =\n CASE\n WHEN \"UpdatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9] [0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9][0-9][0-9]'\n THEN \"UpdatedAt\"\n WHEN \"UpdatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]T[0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9]*'\n THEN substr(\"UpdatedAt\", 1, 10) || ' ' || substr(\"UpdatedAt\", 12, 12)\n WHEN \"UpdatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9][T ][0-9][0-9]:[0-9][0-9]:[0-9][0-9]*'\n THEN substr(\"UpdatedAt\", 1, 10) || ' ' || substr(replace(\"UpdatedAt\", 'T', ' '), 12, 8) || '.000'\n ELSE \"UpdatedAt\"\n END;\n\n-- Update Credentials table (CreatedAt, UpdatedAt)\nUPDATE \"Credentials\" SET \"CreatedAt\" =\n CASE\n WHEN \"CreatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9] [0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9][0-9][0-9]'\n THEN \"CreatedAt\"\n WHEN \"CreatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]T[0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9]*'\n THEN substr(\"CreatedAt\", 1, 10) || ' ' || substr(\"CreatedAt\", 12, 12)\n WHEN \"CreatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9][T ][0-9][0-9]:[0-9][0-9]:[0-9][0-9]*'\n THEN substr(\"CreatedAt\", 1, 10) || ' ' || substr(replace(\"CreatedAt\", 'T', ' '), 12, 8) || '.000'\n ELSE \"CreatedAt\"\n END;\n\nUPDATE \"Credentials\" SET \"UpdatedAt\" =\n CASE\n WHEN \"UpdatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9] [0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9][0-9][0-9]'\n THEN \"UpdatedAt\"\n WHEN \"UpdatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]T[0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9]*'\n THEN substr(\"UpdatedAt\", 1, 10) || ' ' || substr(\"UpdatedAt\", 12, 12)\n WHEN \"UpdatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9][T ][0-9][0-9]:[0-9][0-9]:[0-9][0-9]*'\n THEN substr(\"UpdatedAt\", 1, 10) || ' ' || substr(replace(\"UpdatedAt\", 'T', ' '), 12, 8) || '.000'\n ELSE \"UpdatedAt\"\n END;\n\n-- Update Attachments table (CreatedAt, UpdatedAt)\nUPDATE \"Attachments\" SET \"CreatedAt\" =\n CASE\n WHEN \"CreatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9] [0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9][0-9][0-9]'\n THEN \"CreatedAt\"\n WHEN \"CreatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]T[0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9]*'\n THEN substr(\"CreatedAt\", 1, 10) || ' ' || substr(\"CreatedAt\", 12, 12)\n WHEN \"CreatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9][T ][0-9][0-9]:[0-9][0-9]:[0-9][0-9]*'\n THEN substr(\"CreatedAt\", 1, 10) || ' ' || substr(replace(\"CreatedAt\", 'T', ' '), 12, 8) || '.000'\n ELSE \"CreatedAt\"\n END;\n\nUPDATE \"Attachments\" SET \"UpdatedAt\" =\n CASE\n WHEN \"UpdatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9] [0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9][0-9][0-9]'\n THEN \"UpdatedAt\"\n WHEN \"UpdatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]T[0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9]*'\n THEN substr(\"UpdatedAt\", 1, 10) || ' ' || substr(\"UpdatedAt\", 12, 12)\n WHEN \"UpdatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9][T ][0-9][0-9]:[0-9][0-9]:[0-9][0-9]*'\n THEN substr(\"UpdatedAt\", 1, 10) || ' ' || substr(replace(\"UpdatedAt\", 'T', ' '), 12, 8) || '.000'\n ELSE \"UpdatedAt\"\n END;\n\n-- Update Passwords table (CreatedAt, UpdatedAt)\nUPDATE \"Passwords\" SET \"CreatedAt\" =\n CASE\n WHEN \"CreatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9] [0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9][0-9][0-9]'\n THEN \"CreatedAt\"\n WHEN \"CreatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]T[0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9]*'\n THEN substr(\"CreatedAt\", 1, 10) || ' ' || substr(\"CreatedAt\", 12, 12)\n WHEN \"CreatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9][T ][0-9][0-9]:[0-9][0-9]:[0-9][0-9]*'\n THEN substr(\"CreatedAt\", 1, 10) || ' ' || substr(replace(\"CreatedAt\", 'T', ' '), 12, 8) || '.000'\n ELSE \"CreatedAt\"\n END;\n\nUPDATE \"Passwords\" SET \"UpdatedAt\" =\n CASE\n WHEN \"UpdatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9] [0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9][0-9][0-9]'\n THEN \"UpdatedAt\"\n WHEN \"UpdatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]T[0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9]*'\n THEN substr(\"UpdatedAt\", 1, 10) || ' ' || substr(\"UpdatedAt\", 12, 12)\n WHEN \"UpdatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9][T ][0-9][0-9]:[0-9][0-9]:[0-9][0-9]*'\n THEN substr(\"UpdatedAt\", 1, 10) || ' ' || substr(replace(\"UpdatedAt\", 'T', ' '), 12, 8) || '.000'\n ELSE \"UpdatedAt\"\n END;\n\n-- Update TotpCodes table (CreatedAt, UpdatedAt)\nUPDATE \"TotpCodes\" SET \"CreatedAt\" =\n CASE\n WHEN \"CreatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9] [0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9][0-9][0-9]'\n THEN \"CreatedAt\"\n WHEN \"CreatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]T[0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9]*'\n THEN substr(\"CreatedAt\", 1, 10) || ' ' || substr(\"CreatedAt\", 12, 12)\n WHEN \"CreatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9][T ][0-9][0-9]:[0-9][0-9]:[0-9][0-9]*'\n THEN substr(\"CreatedAt\", 1, 10) || ' ' || substr(replace(\"CreatedAt\", 'T', ' '), 12, 8) || '.000'\n ELSE \"CreatedAt\"\n END;\n\nUPDATE \"TotpCodes\" SET \"UpdatedAt\" =\n CASE\n WHEN \"UpdatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9] [0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9][0-9][0-9]'\n THEN \"UpdatedAt\"\n WHEN \"UpdatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]T[0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9]*'\n THEN substr(\"UpdatedAt\", 1, 10) || ' ' || substr(\"UpdatedAt\", 12, 12)\n WHEN \"UpdatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9][T ][0-9][0-9]:[0-9][0-9]:[0-9][0-9]*'\n THEN substr(\"UpdatedAt\", 1, 10) || ' ' || substr(replace(\"UpdatedAt\", 'T', ' '), 12, 8) || '.000'\n ELSE \"UpdatedAt\"\n END;\n\n-- =====================================================================================\n-- End of Date Format Normalization Migration\n-- =====================================================================================\n\n-- Recreate indexes\nCREATE INDEX \"IX_Credentials_AliasId\" ON \"Credentials\" (\"AliasId\");\nCREATE INDEX \"IX_Credentials_ServiceId\" ON \"Credentials\" (\"ServiceId\");\nCREATE INDEX \"IX_Attachments_CredentialId\" ON \"Attachments\" (\"CredentialId\");\nCREATE INDEX \"IX_Passwords_CredentialId\" ON \"Passwords\" (\"CredentialId\");\nCREATE INDEX \"IX_TotpCodes_CredentialId\" ON \"TotpCodes\" (\"CredentialId\");\n\n-- Clean up temp tables\nDROP TABLE \"__EFMigrationsHistory_temp\";\nDROP TABLE \"Aliases_temp\";\nDROP TABLE \"Services_temp\";\nDROP TABLE \"EncryptionKeys_temp\";\nDROP TABLE \"Settings_temp\";\nDROP TABLE \"Credentials_temp\";\nDROP TABLE \"Attachments_temp\";\nDROP TABLE \"Passwords_temp\";\nDROP TABLE \"TotpCodes_temp\";\n\nPRAGMA foreign_keys = ON;\n\n\nCREATE TABLE \"Passkeys\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_Passkeys\" PRIMARY KEY,\n \"RpId\" TEXT COLLATE NOCASE NOT NULL,\n \"UserHandle\" BLOB NOT NULL,\n \"PublicKey\" TEXT NOT NULL,\n \"PrivateKey\" TEXT NOT NULL,\n \"PrfKey\" BLOB NULL,\n \"DisplayName\" TEXT NOT NULL,\n \"AdditionalData\" BLOB NULL,\n \"CredentialId\" TEXT NOT NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"UpdatedAt\" TEXT NOT NULL,\n \"IsDeleted\" INTEGER NOT NULL,\n CONSTRAINT \"FK_Passkeys_Credentials_CredentialId\" FOREIGN KEY (\"CredentialId\") REFERENCES \"Credentials\" (\"Id\") ON DELETE CASCADE\n);\n\nCREATE INDEX \"IX_Passkeys_CredentialId\" ON \"Passkeys\" (\"CredentialId\");\n\nCREATE INDEX \"IX_Passkeys_RpId\" ON \"Passkeys\" (\"RpId\");\n\nINSERT INTO \"__EFMigrationsHistory\" (\"MigrationId\", \"ProductVersion\")\nVALUES ('20251014122838_1.6.0-AddPasskeys', '9.0.4');\n\nALTER TABLE \"TotpCodes\" RENAME COLUMN \"CredentialId\" TO \"ItemId\";\n\nDROP INDEX IF EXISTS \"IX_TotpCodes_CredentialId\";\n\nCREATE INDEX IF NOT EXISTS \"IX_TotpCodes_ItemId\" ON \"TotpCodes\" (\"ItemId\");\n\nALTER TABLE \"Passkeys\" RENAME COLUMN \"CredentialId\" TO \"ItemId\";\n\nDROP INDEX IF EXISTS \"IX_Passkeys_CredentialId\";\n\nCREATE INDEX IF NOT EXISTS \"IX_Passkeys_ItemId\" ON \"Passkeys\" (\"ItemId\");\n\nALTER TABLE \"Attachments\" RENAME COLUMN \"CredentialId\" TO \"ItemId\";\n\nDROP INDEX IF EXISTS \"IX_Attachments_CredentialId\";\n\nCREATE INDEX IF NOT EXISTS \"IX_Attachments_ItemId\" ON \"Attachments\" (\"ItemId\");\n\nCREATE TABLE \"FieldDefinitions\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_FieldDefinitions\" PRIMARY KEY,\n \"FieldType\" TEXT NOT NULL,\n \"Label\" TEXT NOT NULL,\n \"IsMultiValue\" INTEGER NOT NULL,\n \"IsHidden\" INTEGER NOT NULL,\n \"EnableHistory\" INTEGER NOT NULL,\n \"Weight\" INTEGER NOT NULL,\n \"ApplicableToTypes\" TEXT NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"UpdatedAt\" TEXT NOT NULL,\n \"IsDeleted\" INTEGER NOT NULL\n);\n\nCREATE TABLE \"Folders\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_Folders\" PRIMARY KEY,\n \"Name\" TEXT NOT NULL,\n \"ParentFolderId\" TEXT NULL,\n \"Weight\" INTEGER NOT NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"UpdatedAt\" TEXT NOT NULL,\n \"IsDeleted\" INTEGER NOT NULL,\n CONSTRAINT \"FK_Folders_Folders_ParentFolderId\" FOREIGN KEY (\"ParentFolderId\") REFERENCES \"Folders\" (\"Id\") ON DELETE CASCADE\n);\n\nCREATE TABLE \"Logos\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_Logos\" PRIMARY KEY,\n \"Source\" TEXT NOT NULL,\n \"FileData\" BLOB NULL,\n \"MimeType\" TEXT NULL,\n \"FetchedAt\" TEXT NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"UpdatedAt\" TEXT NOT NULL,\n \"IsDeleted\" INTEGER NOT NULL\n);\n\nCREATE TABLE \"Tags\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_Tags\" PRIMARY KEY,\n \"Name\" TEXT NOT NULL,\n \"Color\" TEXT NULL,\n \"DisplayOrder\" INTEGER NOT NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"UpdatedAt\" TEXT NOT NULL,\n \"IsDeleted\" INTEGER NOT NULL\n);\n\nCREATE TABLE \"Items\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_Items\" PRIMARY KEY,\n \"Name\" TEXT NULL,\n \"ItemType\" TEXT NOT NULL,\n \"LogoId\" TEXT NULL,\n \"DeletedAt\" TEXT NULL,\n \"FolderId\" TEXT NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"UpdatedAt\" TEXT NOT NULL,\n \"IsDeleted\" INTEGER NOT NULL,\n CONSTRAINT \"FK_Items_Folders_FolderId\" FOREIGN KEY (\"FolderId\") REFERENCES \"Folders\" (\"Id\") ON DELETE SET NULL,\n CONSTRAINT \"FK_Items_Logos_LogoId\" FOREIGN KEY (\"LogoId\") REFERENCES \"Logos\" (\"Id\") ON DELETE SET NULL\n);\n\nCREATE TABLE \"FieldHistories\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_FieldHistories\" PRIMARY KEY,\n \"ItemId\" TEXT NOT NULL,\n \"FieldDefinitionId\" TEXT NULL,\n \"FieldKey\" TEXT NULL,\n \"ValueSnapshot\" TEXT NOT NULL,\n \"ChangedAt\" TEXT NOT NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"UpdatedAt\" TEXT NOT NULL,\n \"IsDeleted\" INTEGER NOT NULL,\n CONSTRAINT \"FK_FieldHistories_FieldDefinitions_FieldDefinitionId\" FOREIGN KEY (\"FieldDefinitionId\") REFERENCES \"FieldDefinitions\" (\"Id\") ON DELETE CASCADE,\n CONSTRAINT \"FK_FieldHistories_Items_ItemId\" FOREIGN KEY (\"ItemId\") REFERENCES \"Items\" (\"Id\") ON DELETE CASCADE\n);\n\nCREATE TABLE \"FieldValues\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_FieldValues\" PRIMARY KEY,\n \"ItemId\" TEXT NOT NULL,\n \"FieldDefinitionId\" TEXT NULL,\n \"FieldKey\" TEXT NULL,\n \"Value\" TEXT NULL,\n \"Weight\" INTEGER NOT NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"UpdatedAt\" TEXT NOT NULL,\n \"IsDeleted\" INTEGER NOT NULL,\n CONSTRAINT \"FK_FieldValues_FieldDefinitions_FieldDefinitionId\" FOREIGN KEY (\"FieldDefinitionId\") REFERENCES \"FieldDefinitions\" (\"Id\") ON DELETE CASCADE,\n CONSTRAINT \"FK_FieldValues_Items_ItemId\" FOREIGN KEY (\"ItemId\") REFERENCES \"Items\" (\"Id\") ON DELETE CASCADE\n);\n\nCREATE TABLE \"ItemTags\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_ItemTags\" PRIMARY KEY,\n \"ItemId\" TEXT NOT NULL,\n \"TagId\" TEXT NOT NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"UpdatedAt\" TEXT NOT NULL,\n \"IsDeleted\" INTEGER NOT NULL,\n CONSTRAINT \"FK_ItemTags_Items_ItemId\" FOREIGN KEY (\"ItemId\") REFERENCES \"Items\" (\"Id\") ON DELETE CASCADE,\n CONSTRAINT \"FK_ItemTags_Tags_TagId\" FOREIGN KEY (\"TagId\") REFERENCES \"Tags\" (\"Id\") ON DELETE CASCADE\n);\n\nCREATE INDEX \"IX_FieldHistories_FieldDefinitionId\" ON \"FieldHistories\" (\"FieldDefinitionId\");\n\nCREATE INDEX \"IX_FieldHistories_ItemId\" ON \"FieldHistories\" (\"ItemId\");\n\nCREATE INDEX \"IX_FieldValues_FieldDefinitionId\" ON \"FieldValues\" (\"FieldDefinitionId\");\n\nCREATE INDEX \"IX_FieldValues_FieldKey\" ON \"FieldValues\" (\"FieldKey\");\n\nCREATE INDEX \"IX_FieldValues_ItemId\" ON \"FieldValues\" (\"ItemId\");\n\nCREATE INDEX \"IX_FieldValues_ItemId_FieldDefinitionId_Weight\" ON \"FieldValues\" (\"ItemId\", \"FieldDefinitionId\", \"Weight\");\n\nCREATE INDEX \"IX_FieldValues_ItemId_FieldKey\" ON \"FieldValues\" (\"ItemId\", \"FieldKey\");\n\nCREATE INDEX \"IX_Folders_ParentFolderId\" ON \"Folders\" (\"ParentFolderId\");\n\nCREATE INDEX \"IX_Items_FolderId\" ON \"Items\" (\"FolderId\");\n\nCREATE INDEX \"IX_Items_LogoId\" ON \"Items\" (\"LogoId\");\n\nCREATE INDEX \"IX_ItemTags_ItemId\" ON \"ItemTags\" (\"ItemId\");\n\nCREATE UNIQUE INDEX \"IX_ItemTags_ItemId_TagId\" ON \"ItemTags\" (\"ItemId\", \"TagId\");\n\nCREATE INDEX \"IX_ItemTags_TagId\" ON \"ItemTags\" (\"TagId\");\n\nCREATE UNIQUE INDEX \"IX_Logos_Source\" ON \"Logos\" (\"Source\");\n\nCREATE INDEX \"IX_Tags_Name\" ON \"Tags\" (\"Name\");\n\n\n INSERT INTO Items (Id, Name, ItemType, LogoId, FolderId, CreatedAt, UpdatedAt, IsDeleted)\n SELECT\n c.Id,\n s.Name AS Name,\n CASE\n WHEN a.Id IS NOT NULL AND (\n (a.FirstName IS NOT NULL AND a.FirstName != '') OR\n (a.LastName IS NOT NULL AND a.LastName != '') OR\n (a.Gender IS NOT NULL AND a.Gender != '') OR\n (a.BirthDate IS NOT NULL AND a.BirthDate != '' AND a.BirthDate NOT LIKE '0001-%')\n ) THEN 'Alias'\n ELSE 'Login'\n END AS ItemType,\n NULL AS LogoId,\n NULL AS FolderId,\n c.CreatedAt,\n c.UpdatedAt,\n c.IsDeleted\n FROM Credentials c\n LEFT JOIN Services s ON s.Id = c.ServiceId\n LEFT JOIN Aliases a ON a.Id = c.AliasId;\n \n\n\n INSERT INTO Logos (Id, Source, FileData, MimeType, FetchedAt, CreatedAt, UpdatedAt, IsDeleted)\n SELECT\n UPPER(SUBSTR(hex(randomblob(4)), 1, 8) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(6)), 1, 12)) AS Id,\n -- Extract and normalize hostname: remove protocol, path, lowercase, and www. prefix\n REPLACE(\n LOWER(\n SUBSTR(\n CASE\n WHEN s.Url LIKE 'https://%' THEN SUBSTR(s.Url, 9)\n WHEN s.Url LIKE 'http://%' THEN SUBSTR(s.Url, 8)\n ELSE s.Url\n END,\n 1,\n CASE\n WHEN INSTR(\n CASE\n WHEN s.Url LIKE 'https://%' THEN SUBSTR(s.Url, 9)\n WHEN s.Url LIKE 'http://%' THEN SUBSTR(s.Url, 8)\n ELSE s.Url\n END, '/') > 0\n THEN INSTR(\n CASE\n WHEN s.Url LIKE 'https://%' THEN SUBSTR(s.Url, 9)\n WHEN s.Url LIKE 'http://%' THEN SUBSTR(s.Url, 8)\n ELSE s.Url\n END, '/') - 1\n ELSE LENGTH(\n CASE\n WHEN s.Url LIKE 'https://%' THEN SUBSTR(s.Url, 9)\n WHEN s.Url LIKE 'http://%' THEN SUBSTR(s.Url, 8)\n ELSE s.Url\n END)\n END\n )\n ),\n 'www.', ''\n ) AS Source,\n s.Logo AS FileData,\n 'image/png' AS MimeType,\n NULL AS FetchedAt,\n MIN(s.CreatedAt) AS CreatedAt,\n MAX(s.UpdatedAt) AS UpdatedAt,\n 0 AS IsDeleted\n FROM Services s\n WHERE s.Logo IS NOT NULL AND s.Url IS NOT NULL AND s.Url != ''\n GROUP BY REPLACE(\n LOWER(\n SUBSTR(\n CASE\n WHEN s.Url LIKE 'https://%' THEN SUBSTR(s.Url, 9)\n WHEN s.Url LIKE 'http://%' THEN SUBSTR(s.Url, 8)\n ELSE s.Url\n END,\n 1,\n CASE\n WHEN INSTR(\n CASE\n WHEN s.Url LIKE 'https://%' THEN SUBSTR(s.Url, 9)\n WHEN s.Url LIKE 'http://%' THEN SUBSTR(s.Url, 8)\n ELSE s.Url\n END, '/') > 0\n THEN INSTR(\n CASE\n WHEN s.Url LIKE 'https://%' THEN SUBSTR(s.Url, 9)\n WHEN s.Url LIKE 'http://%' THEN SUBSTR(s.Url, 8)\n ELSE s.Url\n END, '/') - 1\n ELSE LENGTH(\n CASE\n WHEN s.Url LIKE 'https://%' THEN SUBSTR(s.Url, 9)\n WHEN s.Url LIKE 'http://%' THEN SUBSTR(s.Url, 8)\n ELSE s.Url\n END)\n END\n )\n ),\n 'www.', ''\n );\n \n\n\n UPDATE Items\n SET LogoId = (\n SELECT l.Id FROM Logos l\n INNER JOIN Services s ON REPLACE(\n LOWER(\n SUBSTR(\n CASE\n WHEN s.Url LIKE 'https://%' THEN SUBSTR(s.Url, 9)\n WHEN s.Url LIKE 'http://%' THEN SUBSTR(s.Url, 8)\n ELSE s.Url\n END,\n 1,\n CASE\n WHEN INSTR(\n CASE\n WHEN s.Url LIKE 'https://%' THEN SUBSTR(s.Url, 9)\n WHEN s.Url LIKE 'http://%' THEN SUBSTR(s.Url, 8)\n ELSE s.Url\n END, '/') > 0\n THEN INSTR(\n CASE\n WHEN s.Url LIKE 'https://%' THEN SUBSTR(s.Url, 9)\n WHEN s.Url LIKE 'http://%' THEN SUBSTR(s.Url, 8)\n ELSE s.Url\n END, '/') - 1\n ELSE LENGTH(\n CASE\n WHEN s.Url LIKE 'https://%' THEN SUBSTR(s.Url, 9)\n WHEN s.Url LIKE 'http://%' THEN SUBSTR(s.Url, 8)\n ELSE s.Url\n END)\n END\n )\n ),\n 'www.', ''\n ) = l.Source\n INNER JOIN Credentials c ON c.ServiceId = s.Id\n WHERE c.Id = Items.Id\n LIMIT 1\n )\n WHERE EXISTS (\n SELECT 1 FROM Credentials c\n INNER JOIN Services s ON s.Id = c.ServiceId\n WHERE c.Id = Items.Id AND s.Logo IS NOT NULL\n );\n \n\n\n INSERT INTO FieldValues (Id, ItemId, FieldDefinitionId, FieldKey, Value, Weight, CreatedAt, UpdatedAt, IsDeleted)\n SELECT\n UPPER(SUBSTR(hex(randomblob(4)), 1, 8) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(6)), 1, 12)) AS Id,\n c.Id AS ItemId,\n NULL AS FieldDefinitionId,\n 'login.url' AS FieldKey,\n s.Url AS Value,\n 0 AS Weight,\n s.UpdatedAt AS CreatedAt,\n s.UpdatedAt AS UpdatedAt,\n 0 AS IsDeleted\n FROM Credentials c\n INNER JOIN Services s ON s.Id = c.ServiceId\n WHERE s.Url IS NOT NULL AND s.Url != '';\n \n\n\n INSERT INTO FieldValues (Id, ItemId, FieldDefinitionId, FieldKey, Value, Weight, CreatedAt, UpdatedAt, IsDeleted)\n SELECT\n UPPER(SUBSTR(hex(randomblob(4)), 1, 8) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(6)), 1, 12)) AS Id,\n c.Id AS ItemId,\n NULL AS FieldDefinitionId,\n 'login.username' AS FieldKey,\n c.Username AS Value,\n 0 AS Weight,\n c.UpdatedAt AS CreatedAt,\n c.UpdatedAt AS UpdatedAt,\n 0 AS IsDeleted\n FROM Credentials c\n WHERE c.Username IS NOT NULL AND c.Username != '';\n \n\n\n INSERT INTO FieldValues (Id, ItemId, FieldDefinitionId, FieldKey, Value, Weight, CreatedAt, UpdatedAt, IsDeleted)\n SELECT\n UPPER(SUBSTR(hex(randomblob(4)), 1, 8) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(6)), 1, 12)) AS Id,\n c.Id AS ItemId,\n NULL AS FieldDefinitionId,\n 'login.notes' AS FieldKey,\n c.Notes AS Value,\n 0 AS Weight,\n c.UpdatedAt AS CreatedAt,\n c.UpdatedAt AS UpdatedAt,\n 0 AS IsDeleted\n FROM Credentials c\n WHERE c.Notes IS NOT NULL AND c.Notes != '';\n \n\n\n INSERT INTO FieldValues (Id, ItemId, FieldDefinitionId, FieldKey, Value, Weight, CreatedAt, UpdatedAt, IsDeleted)\n SELECT\n UPPER(SUBSTR(hex(randomblob(4)), 1, 8) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(6)), 1, 12)) AS Id,\n p.CredentialId AS ItemId,\n NULL AS FieldDefinitionId,\n 'login.password' AS FieldKey,\n p.Value AS Value,\n 0 AS Weight,\n p.UpdatedAt AS CreatedAt,\n p.UpdatedAt AS UpdatedAt,\n 0 AS IsDeleted\n FROM Passwords p\n INNER JOIN (\n SELECT CredentialId, MAX(UpdatedAt) AS MaxUpdated, MAX(Id) AS MaxId\n FROM Passwords\n WHERE IsDeleted = 0\n GROUP BY CredentialId\n ) pm ON p.CredentialId = pm.CredentialId AND p.UpdatedAt = pm.MaxUpdated AND p.Id = pm.MaxId\n WHERE p.IsDeleted = 0;\n \n\n\n INSERT INTO FieldValues (Id, ItemId, FieldDefinitionId, FieldKey, Value, Weight, CreatedAt, UpdatedAt, IsDeleted)\n SELECT\n UPPER(SUBSTR(hex(randomblob(4)), 1, 8) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(6)), 1, 12)) AS Id,\n c.Id AS ItemId,\n NULL AS FieldDefinitionId,\n 'login.email' AS FieldKey,\n a.Email AS Value,\n 0 AS Weight,\n a.UpdatedAt AS CreatedAt,\n a.UpdatedAt AS UpdatedAt,\n 0 AS IsDeleted\n FROM Credentials c\n INNER JOIN Aliases a ON a.Id = c.AliasId\n WHERE a.Email IS NOT NULL AND a.Email != '';\n \n\n\n INSERT INTO FieldValues (Id, ItemId, FieldDefinitionId, FieldKey, Value, Weight, CreatedAt, UpdatedAt, IsDeleted)\n SELECT\n UPPER(SUBSTR(hex(randomblob(4)), 1, 8) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(6)), 1, 12)) AS Id,\n c.Id AS ItemId,\n NULL AS FieldDefinitionId,\n 'alias.first_name' AS FieldKey,\n a.FirstName AS Value,\n 0 AS Weight,\n a.UpdatedAt AS CreatedAt,\n a.UpdatedAt AS UpdatedAt,\n 0 AS IsDeleted\n FROM Credentials c\n INNER JOIN Aliases a ON a.Id = c.AliasId\n WHERE a.FirstName IS NOT NULL AND a.FirstName != '';\n \n\n\n INSERT INTO FieldValues (Id, ItemId, FieldDefinitionId, FieldKey, Value, Weight, CreatedAt, UpdatedAt, IsDeleted)\n SELECT\n UPPER(SUBSTR(hex(randomblob(4)), 1, 8) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(6)), 1, 12)) AS Id,\n c.Id AS ItemId,\n NULL AS FieldDefinitionId,\n 'alias.last_name' AS FieldKey,\n a.LastName AS Value,\n 0 AS Weight,\n a.UpdatedAt AS CreatedAt,\n a.UpdatedAt AS UpdatedAt,\n 0 AS IsDeleted\n FROM Credentials c\n INNER JOIN Aliases a ON a.Id = c.AliasId\n WHERE a.LastName IS NOT NULL AND a.LastName != '';\n \n\n\n INSERT INTO FieldValues (Id, ItemId, FieldDefinitionId, FieldKey, Value, Weight, CreatedAt, UpdatedAt, IsDeleted)\n SELECT\n UPPER(SUBSTR(hex(randomblob(4)), 1, 8) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(6)), 1, 12)) AS Id,\n c.Id AS ItemId,\n NULL AS FieldDefinitionId,\n 'alias.gender' AS FieldKey,\n a.Gender AS Value,\n 0 AS Weight,\n a.UpdatedAt AS CreatedAt,\n a.UpdatedAt AS UpdatedAt,\n 0 AS IsDeleted\n FROM Credentials c\n INNER JOIN Aliases a ON a.Id = c.AliasId\n WHERE a.Gender IS NOT NULL AND a.Gender != '';\n \n\n\n INSERT INTO FieldValues (Id, ItemId, FieldDefinitionId, FieldKey, Value, Weight, CreatedAt, UpdatedAt, IsDeleted)\n SELECT\n UPPER(SUBSTR(hex(randomblob(4)), 1, 8) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(6)), 1, 12)) AS Id,\n c.Id AS ItemId,\n NULL AS FieldDefinitionId,\n 'alias.birthdate' AS FieldKey,\n SUBSTR(a.BirthDate, 1, 10) AS Value,\n 0 AS Weight,\n a.UpdatedAt AS CreatedAt,\n a.UpdatedAt AS UpdatedAt,\n 0 AS IsDeleted\n FROM Credentials c\n INNER JOIN Aliases a ON a.Id = c.AliasId\n WHERE a.BirthDate IS NOT NULL AND a.BirthDate != '' AND a.BirthDate NOT LIKE '0001-%';\n \n\nDROP TABLE \"Passwords\";\n\nDROP TABLE \"Credentials\";\n\nDROP TABLE \"Aliases\";\n\nDROP TABLE \"Services\";\n\nCREATE TABLE \"ef_temp_Attachments\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_Attachments\" PRIMARY KEY,\n \"Blob\" BLOB NOT NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"Filename\" TEXT NOT NULL,\n \"IsDeleted\" INTEGER NOT NULL,\n \"ItemId\" TEXT NOT NULL,\n \"UpdatedAt\" TEXT NOT NULL,\n CONSTRAINT \"FK_Attachments_Items_ItemId\" FOREIGN KEY (\"ItemId\") REFERENCES \"Items\" (\"Id\") ON DELETE CASCADE\n);\n\nINSERT INTO \"ef_temp_Attachments\" (\"Id\", \"Blob\", \"CreatedAt\", \"Filename\", \"IsDeleted\", \"ItemId\", \"UpdatedAt\")\nSELECT \"Id\", \"Blob\", \"CreatedAt\", \"Filename\", \"IsDeleted\", \"ItemId\", \"UpdatedAt\"\nFROM \"Attachments\";\n\nCREATE TABLE \"ef_temp_Passkeys\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_Passkeys\" PRIMARY KEY,\n \"AdditionalData\" BLOB NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"DisplayName\" TEXT NOT NULL,\n \"IsDeleted\" INTEGER NOT NULL,\n \"ItemId\" TEXT NOT NULL,\n \"PrfKey\" BLOB NULL,\n \"PrivateKey\" TEXT NOT NULL,\n \"PublicKey\" TEXT NOT NULL,\n \"RpId\" TEXT COLLATE NOCASE NOT NULL,\n \"UpdatedAt\" TEXT NOT NULL,\n \"UserHandle\" BLOB NOT NULL,\n CONSTRAINT \"FK_Passkeys_Items_ItemId\" FOREIGN KEY (\"ItemId\") REFERENCES \"Items\" (\"Id\") ON DELETE CASCADE\n);\n\nINSERT INTO \"ef_temp_Passkeys\" (\"Id\", \"AdditionalData\", \"CreatedAt\", \"DisplayName\", \"IsDeleted\", \"ItemId\", \"PrfKey\", \"PrivateKey\", \"PublicKey\", \"RpId\", \"UpdatedAt\", \"UserHandle\")\nSELECT \"Id\", \"AdditionalData\", \"CreatedAt\", \"DisplayName\", \"IsDeleted\", \"ItemId\", \"PrfKey\", \"PrivateKey\", \"PublicKey\", \"RpId\", \"UpdatedAt\", \"UserHandle\"\nFROM \"Passkeys\";\n\nCREATE TABLE \"ef_temp_TotpCodes\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_TotpCodes\" PRIMARY KEY,\n \"CreatedAt\" TEXT NOT NULL,\n \"IsDeleted\" INTEGER NOT NULL,\n \"ItemId\" TEXT NOT NULL,\n \"Name\" TEXT NOT NULL,\n \"SecretKey\" TEXT NOT NULL,\n \"UpdatedAt\" TEXT NOT NULL,\n CONSTRAINT \"FK_TotpCodes_Items_ItemId\" FOREIGN KEY (\"ItemId\") REFERENCES \"Items\" (\"Id\") ON DELETE CASCADE\n);\n\nINSERT INTO \"ef_temp_TotpCodes\" (\"Id\", \"CreatedAt\", \"IsDeleted\", \"ItemId\", \"Name\", \"SecretKey\", \"UpdatedAt\")\nSELECT \"Id\", \"CreatedAt\", \"IsDeleted\", \"ItemId\", \"Name\", \"SecretKey\", \"UpdatedAt\"\nFROM \"TotpCodes\";\n\nCOMMIT;\n\nPRAGMA foreign_keys = 0;\n\nBEGIN TRANSACTION;\nDROP TABLE \"Attachments\";\n\nALTER TABLE \"ef_temp_Attachments\" RENAME TO \"Attachments\";\n\nDROP TABLE \"Passkeys\";\n\nALTER TABLE \"ef_temp_Passkeys\" RENAME TO \"Passkeys\";\n\nDROP TABLE \"TotpCodes\";\n\nALTER TABLE \"ef_temp_TotpCodes\" RENAME TO \"TotpCodes\";\n\nCOMMIT;\n\nPRAGMA foreign_keys = 1;\n\nBEGIN TRANSACTION;\nCREATE INDEX \"IX_Attachments_ItemId\" ON \"Attachments\" (\"ItemId\");\n\nCREATE INDEX \"IX_Passkeys_ItemId\" ON \"Passkeys\" (\"ItemId\");\n\nCREATE INDEX \"IX_Passkeys_RpId\" ON \"Passkeys\" (\"RpId\");\n\nCREATE INDEX \"IX_TotpCodes_ItemId\" ON \"TotpCodes\" (\"ItemId\");\n\nCOMMIT;\n\nINSERT INTO \"__EFMigrationsHistory\" (\"MigrationId\", \"ProductVersion\")\nVALUES ('20251213111207_1.7.0-FieldBasedDataModelUpdate', '9.0.4');\n\nBEGIN TRANSACTION;\nINSERT INTO \"__EFMigrationsHistory\" (\"MigrationId\", \"ProductVersion\")\nVALUES ('20260130221620_2.0.0-MajorVersionBump', '9.0.4');\n\nCOMMIT;\n"; /** * Individual migration SQL scripts * Auto-generated from EF Core migrations diff --git a/apps/mobile-app/utils/dist/core/vault/index.d.ts b/apps/mobile-app/utils/dist/core/vault/index.d.ts index 033a999f0..0ee327dbe 100644 --- a/apps/mobile-app/utils/dist/core/vault/index.d.ts +++ b/apps/mobile-app/utils/dist/core/vault/index.d.ts @@ -122,7 +122,7 @@ declare const VAULT_VERSIONS: VaultVersion[]; * Complete database schema SQL (latest version) * Auto-generated from EF Core migrations */ -declare const COMPLETE_SCHEMA_SQL = "\n\uFEFFCREATE TABLE IF NOT EXISTS \"__EFMigrationsHistory\" (\n \"MigrationId\" TEXT NOT NULL CONSTRAINT \"PK___EFMigrationsHistory\" PRIMARY KEY,\n \"ProductVersion\" TEXT NOT NULL\n);\n\nBEGIN TRANSACTION;\nCREATE TABLE \"Aliases\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_Aliases\" PRIMARY KEY,\n \"Gender\" VARCHAR NULL,\n \"FirstName\" VARCHAR NULL,\n \"LastName\" VARCHAR NULL,\n \"NickName\" VARCHAR NULL,\n \"BirthDate\" TEXT NOT NULL,\n \"AddressStreet\" VARCHAR NULL,\n \"AddressCity\" VARCHAR NULL,\n \"AddressState\" VARCHAR NULL,\n \"AddressZipCode\" VARCHAR NULL,\n \"AddressCountry\" VARCHAR NULL,\n \"Hobbies\" TEXT NULL,\n \"EmailPrefix\" TEXT NULL,\n \"PhoneMobile\" TEXT NULL,\n \"BankAccountIBAN\" TEXT NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"UpdatedAt\" TEXT NOT NULL\n);\n\nCREATE TABLE \"Services\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_Services\" PRIMARY KEY,\n \"Name\" TEXT NULL,\n \"Url\" TEXT NULL,\n \"Logo\" BLOB NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"UpdatedAt\" TEXT NOT NULL\n);\n\nCREATE TABLE \"Credentials\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_Credentials\" PRIMARY KEY,\n \"AliasId\" TEXT NOT NULL,\n \"Notes\" TEXT NULL,\n \"Username\" TEXT NOT NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"UpdatedAt\" TEXT NOT NULL,\n \"ServiceId\" TEXT NOT NULL,\n CONSTRAINT \"FK_Credentials_Aliases_AliasId\" FOREIGN KEY (\"AliasId\") REFERENCES \"Aliases\" (\"Id\") ON DELETE CASCADE,\n CONSTRAINT \"FK_Credentials_Services_ServiceId\" FOREIGN KEY (\"ServiceId\") REFERENCES \"Services\" (\"Id\") ON DELETE CASCADE\n);\n\nCREATE TABLE \"Attachment\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_Attachment\" PRIMARY KEY,\n \"Filename\" TEXT NOT NULL,\n \"Blob\" BLOB NOT NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"UpdatedAt\" TEXT NOT NULL,\n \"CredentialId\" TEXT NOT NULL,\n CONSTRAINT \"FK_Attachment_Credentials_CredentialId\" FOREIGN KEY (\"CredentialId\") REFERENCES \"Credentials\" (\"Id\") ON DELETE CASCADE\n);\n\nCREATE TABLE \"Passwords\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_Passwords\" PRIMARY KEY,\n \"Value\" TEXT NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"UpdatedAt\" TEXT NOT NULL,\n \"CredentialId\" TEXT NOT NULL,\n CONSTRAINT \"FK_Passwords_Credentials_CredentialId\" FOREIGN KEY (\"CredentialId\") REFERENCES \"Credentials\" (\"Id\") ON DELETE CASCADE\n);\n\nCREATE INDEX \"IX_Attachment_CredentialId\" ON \"Attachment\" (\"CredentialId\");\n\nCREATE INDEX \"IX_Credentials_AliasId\" ON \"Credentials\" (\"AliasId\");\n\nCREATE INDEX \"IX_Credentials_ServiceId\" ON \"Credentials\" (\"ServiceId\");\n\nCREATE INDEX \"IX_Passwords_CredentialId\" ON \"Passwords\" (\"CredentialId\");\n\nINSERT INTO \"__EFMigrationsHistory\" (\"MigrationId\", \"ProductVersion\")\nVALUES ('20240708094944_1.0.0-InitialMigration', '9.0.4');\n\nINSERT INTO \"__EFMigrationsHistory\" (\"MigrationId\", \"ProductVersion\")\nVALUES ('20240708224522_1.0.1-EmptyTestMigration', '9.0.4');\n\nALTER TABLE \"Aliases\" RENAME COLUMN \"EmailPrefix\" TO \"Email\";\n\nINSERT INTO \"__EFMigrationsHistory\" (\"MigrationId\", \"ProductVersion\")\nVALUES ('20240711204207_1.0.2-ChangeEmailColumn', '9.0.4');\n\nCREATE TABLE \"EncryptionKeys\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_EncryptionKeys\" PRIMARY KEY,\n \"PublicKey\" TEXT NOT NULL,\n \"PrivateKey\" TEXT NOT NULL,\n \"IsPrimary\" INTEGER NOT NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"UpdatedAt\" TEXT NOT NULL\n);\n\nINSERT INTO \"__EFMigrationsHistory\" (\"MigrationId\", \"ProductVersion\")\nVALUES ('20240729105618_1.1.0-AddPkiTables', '9.0.4');\n\nCREATE TABLE \"Settings\" (\n \"Key\" TEXT NOT NULL CONSTRAINT \"PK_Settings\" PRIMARY KEY,\n \"Value\" TEXT NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"UpdatedAt\" TEXT NOT NULL\n);\n\nINSERT INTO \"__EFMigrationsHistory\" (\"MigrationId\", \"ProductVersion\")\nVALUES ('20240805073413_1.2.0-AddSettingsTable', '9.0.4');\n\nCREATE TABLE \"ef_temp_Aliases\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_Aliases\" PRIMARY KEY,\n \"BirthDate\" TEXT NOT NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"Email\" TEXT NULL,\n \"FirstName\" VARCHAR NULL,\n \"Gender\" VARCHAR NULL,\n \"LastName\" VARCHAR NULL,\n \"NickName\" VARCHAR NULL,\n \"UpdatedAt\" TEXT NOT NULL\n);\n\nINSERT INTO \"ef_temp_Aliases\" (\"Id\", \"BirthDate\", \"CreatedAt\", \"Email\", \"FirstName\", \"Gender\", \"LastName\", \"NickName\", \"UpdatedAt\")\nSELECT \"Id\", \"BirthDate\", \"CreatedAt\", \"Email\", \"FirstName\", \"Gender\", \"LastName\", \"NickName\", \"UpdatedAt\"\nFROM \"Aliases\";\n\nCOMMIT;\n\nPRAGMA foreign_keys = 0;\n\nBEGIN TRANSACTION;\nDROP TABLE \"Aliases\";\n\nALTER TABLE \"ef_temp_Aliases\" RENAME TO \"Aliases\";\n\nCOMMIT;\n\nPRAGMA foreign_keys = 1;\n\nINSERT INTO \"__EFMigrationsHistory\" (\"MigrationId\", \"ProductVersion\")\nVALUES ('20240805122422_1.3.0-UpdateIdentityStructure', '9.0.4');\n\nBEGIN TRANSACTION;\nCREATE TABLE \"ef_temp_Credentials\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_Credentials\" PRIMARY KEY,\n \"AliasId\" TEXT NOT NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"Notes\" TEXT NULL,\n \"ServiceId\" TEXT NOT NULL,\n \"UpdatedAt\" TEXT NOT NULL,\n \"Username\" TEXT NULL,\n CONSTRAINT \"FK_Credentials_Aliases_AliasId\" FOREIGN KEY (\"AliasId\") REFERENCES \"Aliases\" (\"Id\") ON DELETE CASCADE,\n CONSTRAINT \"FK_Credentials_Services_ServiceId\" FOREIGN KEY (\"ServiceId\") REFERENCES \"Services\" (\"Id\") ON DELETE CASCADE\n);\n\nINSERT INTO \"ef_temp_Credentials\" (\"Id\", \"AliasId\", \"CreatedAt\", \"Notes\", \"ServiceId\", \"UpdatedAt\", \"Username\")\nSELECT \"Id\", \"AliasId\", \"CreatedAt\", \"Notes\", \"ServiceId\", \"UpdatedAt\", \"Username\"\nFROM \"Credentials\";\n\nCOMMIT;\n\nPRAGMA foreign_keys = 0;\n\nBEGIN TRANSACTION;\nDROP TABLE \"Credentials\";\n\nALTER TABLE \"ef_temp_Credentials\" RENAME TO \"Credentials\";\n\nCOMMIT;\n\nPRAGMA foreign_keys = 1;\n\nBEGIN TRANSACTION;\nCREATE INDEX \"IX_Credentials_AliasId\" ON \"Credentials\" (\"AliasId\");\n\nCREATE INDEX \"IX_Credentials_ServiceId\" ON \"Credentials\" (\"ServiceId\");\n\nCOMMIT;\n\nINSERT INTO \"__EFMigrationsHistory\" (\"MigrationId\", \"ProductVersion\")\nVALUES ('20240812141727_1.3.1-MakeUsernameOptional', '9.0.4');\n\nBEGIN TRANSACTION;\nALTER TABLE \"Settings\" ADD \"IsDeleted\" INTEGER NOT NULL DEFAULT 0;\n\nALTER TABLE \"Services\" ADD \"IsDeleted\" INTEGER NOT NULL DEFAULT 0;\n\nALTER TABLE \"Passwords\" ADD \"IsDeleted\" INTEGER NOT NULL DEFAULT 0;\n\nALTER TABLE \"EncryptionKeys\" ADD \"IsDeleted\" INTEGER NOT NULL DEFAULT 0;\n\nALTER TABLE \"Credentials\" ADD \"IsDeleted\" INTEGER NOT NULL DEFAULT 0;\n\nALTER TABLE \"Attachment\" ADD \"IsDeleted\" INTEGER NOT NULL DEFAULT 0;\n\nALTER TABLE \"Aliases\" ADD \"IsDeleted\" INTEGER NOT NULL DEFAULT 0;\n\nINSERT INTO \"__EFMigrationsHistory\" (\"MigrationId\", \"ProductVersion\")\nVALUES ('20240916105320_1.4.0-AddSyncSupport', '9.0.4');\n\nALTER TABLE \"Attachment\" RENAME TO \"Attachments\";\n\nCREATE TABLE \"ef_temp_Attachments\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_Attachments\" PRIMARY KEY,\n \"Blob\" BLOB NOT NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"CredentialId\" TEXT NOT NULL,\n \"Filename\" TEXT NOT NULL,\n \"IsDeleted\" INTEGER NOT NULL,\n \"UpdatedAt\" TEXT NOT NULL,\n CONSTRAINT \"FK_Attachments_Credentials_CredentialId\" FOREIGN KEY (\"CredentialId\") REFERENCES \"Credentials\" (\"Id\") ON DELETE CASCADE\n);\n\nINSERT INTO \"ef_temp_Attachments\" (\"Id\", \"Blob\", \"CreatedAt\", \"CredentialId\", \"Filename\", \"IsDeleted\", \"UpdatedAt\")\nSELECT \"Id\", \"Blob\", \"CreatedAt\", \"CredentialId\", \"Filename\", \"IsDeleted\", \"UpdatedAt\"\nFROM \"Attachments\";\n\nCOMMIT;\n\nPRAGMA foreign_keys = 0;\n\nBEGIN TRANSACTION;\nDROP TABLE \"Attachments\";\n\nALTER TABLE \"ef_temp_Attachments\" RENAME TO \"Attachments\";\n\nCOMMIT;\n\nPRAGMA foreign_keys = 1;\n\nBEGIN TRANSACTION;\nCREATE INDEX \"IX_Attachments_CredentialId\" ON \"Attachments\" (\"CredentialId\");\n\nCOMMIT;\n\nINSERT INTO \"__EFMigrationsHistory\" (\"MigrationId\", \"ProductVersion\")\nVALUES ('20240917191243_1.4.1-RenameAttachmentsPlural', '9.0.4');\n\nBEGIN TRANSACTION;\nCREATE TABLE \"TotpCodes\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_TotpCodes\" PRIMARY KEY,\n \"Name\" TEXT NOT NULL,\n \"SecretKey\" TEXT NOT NULL,\n \"CredentialId\" TEXT NOT NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"UpdatedAt\" TEXT NOT NULL,\n \"IsDeleted\" INTEGER NOT NULL,\n CONSTRAINT \"FK_TotpCodes_Credentials_CredentialId\" FOREIGN KEY (\"CredentialId\") REFERENCES \"Credentials\" (\"Id\") ON DELETE CASCADE\n);\n\nCREATE INDEX \"IX_TotpCodes_CredentialId\" ON \"TotpCodes\" (\"CredentialId\");\n\nINSERT INTO \"__EFMigrationsHistory\" (\"MigrationId\", \"ProductVersion\")\nVALUES ('20250310131554_1.5.0-AddTotpCodes', '9.0.4');\n\n\nPRAGMA foreign_keys = OFF;\n\n-- Clean up any existing temp tables first\nDROP TABLE IF EXISTS \"__EFMigrationsHistory_temp\";\nDROP TABLE IF EXISTS \"Aliases_temp\";\nDROP TABLE IF EXISTS \"Services_temp\";\nDROP TABLE IF EXISTS \"EncryptionKeys_temp\";\nDROP TABLE IF EXISTS \"Settings_temp\";\nDROP TABLE IF EXISTS \"Credentials_temp\";\nDROP TABLE IF EXISTS \"Attachments_temp\";\nDROP TABLE IF EXISTS \"Passwords_temp\";\nDROP TABLE IF EXISTS \"TotpCodes_temp\";\n\n-- Create backup tables for all data\nCREATE TABLE \"__EFMigrationsHistory_temp\" AS SELECT * FROM \"__EFMigrationsHistory\";\nCREATE TABLE \"Aliases_temp\" AS SELECT * FROM \"Aliases\";\nCREATE TABLE \"Services_temp\" AS SELECT * FROM \"Services\";\nCREATE TABLE \"EncryptionKeys_temp\" AS SELECT * FROM \"EncryptionKeys\";\nCREATE TABLE \"Settings_temp\" AS SELECT * FROM \"Settings\";\nCREATE TABLE \"Credentials_temp\" AS SELECT * FROM \"Credentials\";\nCREATE TABLE \"Attachments_temp\" AS SELECT * FROM \"Attachments\";\nCREATE TABLE \"Passwords_temp\" AS SELECT * FROM \"Passwords\";\nCREATE TABLE \"TotpCodes_temp\" AS SELECT * FROM \"TotpCodes\";\n\n-- Delete orphaned records that do not have a valid FK to the credential object\nDELETE FROM \"Attachments_temp\" WHERE \"CredentialId\" NOT IN (SELECT \"Id\" FROM \"Credentials_temp\");\nDELETE FROM \"Passwords_temp\" WHERE \"CredentialId\" NOT IN (SELECT \"Id\" FROM \"Credentials_temp\");\nDELETE FROM \"TotpCodes_temp\" WHERE \"CredentialId\" NOT IN (SELECT \"Id\" FROM \"Credentials_temp\");\n\n-- Delete orphaned credentials that do not have valid FKs to alias or service objects\nDELETE FROM \"Credentials_temp\" WHERE \"AliasId\" NOT IN (SELECT \"Id\" FROM \"Aliases_temp\");\nDELETE FROM \"Credentials_temp\" WHERE \"ServiceId\" NOT IN (SELECT \"Id\" FROM \"Services_temp\");\n\n-- After cleaning credentials, clean dependent tables again in case we removed credentials\nDELETE FROM \"Attachments_temp\" WHERE \"CredentialId\" NOT IN (SELECT \"Id\" FROM \"Credentials_temp\");\nDELETE FROM \"Passwords_temp\" WHERE \"CredentialId\" NOT IN (SELECT \"Id\" FROM \"Credentials_temp\");\nDELETE FROM \"TotpCodes_temp\" WHERE \"CredentialId\" NOT IN (SELECT \"Id\" FROM \"Credentials_temp\");\n\n-- Drop all existing tables\nDROP TABLE \"TotpCodes\";\nDROP TABLE \"Passwords\";\nDROP TABLE \"Attachments\";\nDROP TABLE \"Credentials\";\nDROP TABLE \"Settings\";\nDROP TABLE \"EncryptionKeys\";\nDROP TABLE \"Services\";\nDROP TABLE \"Aliases\";\nDROP TABLE \"__EFMigrationsHistory\";\n\n-- Recreate tables with proper constraints (no dependencies first)\nCREATE TABLE \"__EFMigrationsHistory\" (\n \"MigrationId\" TEXT NOT NULL CONSTRAINT \"PK___EFMigrationsHistory\" PRIMARY KEY,\n \"ProductVersion\" TEXT NOT NULL\n);\n\nCREATE TABLE \"Aliases\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_Aliases\" PRIMARY KEY,\n \"BirthDate\" TEXT NOT NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"Email\" TEXT NULL,\n \"FirstName\" VARCHAR NULL,\n \"Gender\" VARCHAR NULL,\n \"LastName\" VARCHAR NULL,\n \"NickName\" VARCHAR NULL,\n \"UpdatedAt\" TEXT NOT NULL,\n \"IsDeleted\" INTEGER NOT NULL DEFAULT 0\n);\n\nCREATE TABLE \"Services\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_Services\" PRIMARY KEY,\n \"Name\" TEXT NULL,\n \"Url\" TEXT NULL,\n \"Logo\" BLOB NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"UpdatedAt\" TEXT NOT NULL,\n \"IsDeleted\" INTEGER NOT NULL DEFAULT 0\n);\n\nCREATE TABLE \"EncryptionKeys\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_EncryptionKeys\" PRIMARY KEY,\n \"PublicKey\" TEXT NOT NULL,\n \"PrivateKey\" TEXT NOT NULL,\n \"IsPrimary\" INTEGER NOT NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"UpdatedAt\" TEXT NOT NULL,\n \"IsDeleted\" INTEGER NOT NULL DEFAULT 0\n);\n\nCREATE TABLE \"Settings\" (\n \"Key\" TEXT NOT NULL CONSTRAINT \"PK_Settings\" PRIMARY KEY,\n \"Value\" TEXT NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"UpdatedAt\" TEXT NOT NULL,\n \"IsDeleted\" INTEGER NOT NULL DEFAULT 0\n);\n\n-- Tables with foreign keys\nCREATE TABLE \"Credentials\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_Credentials\" PRIMARY KEY,\n \"AliasId\" TEXT NOT NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"Notes\" TEXT NULL,\n \"ServiceId\" TEXT NOT NULL,\n \"UpdatedAt\" TEXT NOT NULL,\n \"Username\" TEXT NULL,\n \"IsDeleted\" INTEGER NOT NULL DEFAULT 0,\n CONSTRAINT \"FK_Credentials_Aliases_AliasId\" FOREIGN KEY (\"AliasId\") REFERENCES \"Aliases\" (\"Id\") ON DELETE CASCADE,\n CONSTRAINT \"FK_Credentials_Services_ServiceId\" FOREIGN KEY (\"ServiceId\") REFERENCES \"Services\" (\"Id\") ON DELETE CASCADE\n);\n\nCREATE TABLE \"Attachments\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_Attachments\" PRIMARY KEY,\n \"Blob\" BLOB NOT NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"CredentialId\" TEXT NOT NULL,\n \"Filename\" TEXT NOT NULL,\n \"IsDeleted\" INTEGER NOT NULL DEFAULT 0,\n \"UpdatedAt\" TEXT NOT NULL,\n CONSTRAINT \"FK_Attachments_Credentials_CredentialId\" FOREIGN KEY (\"CredentialId\") REFERENCES \"Credentials\" (\"Id\") ON DELETE CASCADE\n);\n\nCREATE TABLE \"Passwords\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_Passwords\" PRIMARY KEY,\n \"Value\" TEXT NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"UpdatedAt\" TEXT NOT NULL,\n \"CredentialId\" TEXT NOT NULL,\n \"IsDeleted\" INTEGER NOT NULL DEFAULT 0,\n CONSTRAINT \"FK_Passwords_Credentials_CredentialId\" FOREIGN KEY (\"CredentialId\") REFERENCES \"Credentials\" (\"Id\") ON DELETE CASCADE\n);\n\nCREATE TABLE \"TotpCodes\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_TotpCodes\" PRIMARY KEY,\n \"Name\" TEXT NOT NULL,\n \"SecretKey\" TEXT NOT NULL,\n \"CredentialId\" TEXT NOT NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"UpdatedAt\" TEXT NOT NULL,\n \"IsDeleted\" INTEGER NOT NULL DEFAULT 0,\n CONSTRAINT \"FK_TotpCodes_Credentials_CredentialId\" FOREIGN KEY (\"CredentialId\") REFERENCES \"Credentials\" (\"Id\") ON DELETE CASCADE\n);\n\n\n-- Restore data from temp tables\nINSERT INTO \"__EFMigrationsHistory\" SELECT * FROM \"__EFMigrationsHistory_temp\";\nINSERT INTO \"Aliases\" SELECT * FROM \"Aliases_temp\";\nINSERT INTO \"Services\" SELECT * FROM \"Services_temp\";\nINSERT INTO \"EncryptionKeys\" SELECT * FROM \"EncryptionKeys_temp\";\nINSERT INTO \"Settings\" SELECT * FROM \"Settings_temp\";\nINSERT INTO \"Credentials\" SELECT * FROM \"Credentials_temp\";\nINSERT INTO \"Attachments\" SELECT * FROM \"Attachments_temp\";\nINSERT INTO \"Passwords\" SELECT * FROM \"Passwords_temp\";\nINSERT INTO \"TotpCodes\" SELECT * FROM \"TotpCodes_temp\";\n\n-- =====================================================================================\n-- Date Format Normalization Migration\n-- =====================================================================================\n-- This migration normalizes ALL date fields to the standard format: 'yyyy-MM-dd HH:mm:ss.fff'\n-- Previously the different clients used different date formats which complicate date parsing.\n-- From version 0.24.0 onwards, all new dates are stored in this standard format.\n\n-- Update Aliases table (CreatedAt, UpdatedAt, BirthDate)\nUPDATE \"Aliases\" SET \"CreatedAt\" =\n CASE\n -- Already in correct format (yyyy-MM-dd HH:mm:ss.fff) - no change\n WHEN \"CreatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9] [0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9][0-9][0-9]'\n THEN \"CreatedAt\"\n\n -- ISO 8601 with milliseconds (yyyy-MM-ddTHH:mm:ss.fffZ) -> Replace T with space, remove Z and everything after .fff\n WHEN \"CreatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]T[0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9]*'\n THEN substr(\"CreatedAt\", 1, 10) || ' ' || substr(\"CreatedAt\", 12, 12)\n\n -- Without milliseconds (yyyy-MM-dd HH:mm:ss or yyyy-MM-ddTHH:mm:ssZ) -> Add .000\n WHEN \"CreatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9][T ][0-9][0-9]:[0-9][0-9]:[0-9][0-9]*'\n THEN substr(\"CreatedAt\", 1, 10) || ' ' || substr(replace(\"CreatedAt\", 'T', ' '), 12, 8) || '.000'\n\n -- Fallback: if none match, keep as-is (edge case)\n ELSE \"CreatedAt\"\n END;\n\nUPDATE \"Aliases\" SET \"UpdatedAt\" =\n CASE\n WHEN \"UpdatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9] [0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9][0-9][0-9]'\n THEN \"UpdatedAt\"\n WHEN \"UpdatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]T[0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9]*'\n THEN substr(\"UpdatedAt\", 1, 10) || ' ' || substr(\"UpdatedAt\", 12, 12)\n WHEN \"UpdatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9][T ][0-9][0-9]:[0-9][0-9]:[0-9][0-9]*'\n THEN substr(\"UpdatedAt\", 1, 10) || ' ' || substr(replace(\"UpdatedAt\", 'T', ' '), 12, 8) || '.000'\n ELSE \"UpdatedAt\"\n END;\n\n-- BirthDate: Always set time to 00:00:00 (no milliseconds for birth dates)\nUPDATE \"Aliases\" SET \"BirthDate\" =\n CASE\n -- If empty or already '0001-01-01 00:00:00', keep as-is\n WHEN \"BirthDate\" = '' OR \"BirthDate\" = '0001-01-01 00:00:00'\n THEN \"BirthDate\"\n\n -- If already in correct format (yyyy-MM-dd 00:00:00), keep as-is\n WHEN \"BirthDate\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9] 00:00:00'\n THEN \"BirthDate\"\n\n -- Extract date part and set time to 00:00:00\n WHEN \"BirthDate\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]*'\n THEN substr(\"BirthDate\", 1, 10) || ' 00:00:00'\n\n -- Fallback\n ELSE \"BirthDate\"\n END;\n\n-- Update Services table (CreatedAt, UpdatedAt)\nUPDATE \"Services\" SET \"CreatedAt\" =\n CASE\n WHEN \"CreatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9] [0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9][0-9][0-9]'\n THEN \"CreatedAt\"\n WHEN \"CreatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]T[0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9]*'\n THEN substr(\"CreatedAt\", 1, 10) || ' ' || substr(\"CreatedAt\", 12, 12)\n WHEN \"CreatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9][T ][0-9][0-9]:[0-9][0-9]:[0-9][0-9]*'\n THEN substr(\"CreatedAt\", 1, 10) || ' ' || substr(replace(\"CreatedAt\", 'T', ' '), 12, 8) || '.000'\n ELSE \"CreatedAt\"\n END;\n\nUPDATE \"Services\" SET \"UpdatedAt\" =\n CASE\n WHEN \"UpdatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9] [0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9][0-9][0-9]'\n THEN \"UpdatedAt\"\n WHEN \"UpdatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]T[0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9]*'\n THEN substr(\"UpdatedAt\", 1, 10) || ' ' || substr(\"UpdatedAt\", 12, 12)\n WHEN \"UpdatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9][T ][0-9][0-9]:[0-9][0-9]:[0-9][0-9]*'\n THEN substr(\"UpdatedAt\", 1, 10) || ' ' || substr(replace(\"UpdatedAt\", 'T', ' '), 12, 8) || '.000'\n ELSE \"UpdatedAt\"\n END;\n\n-- Update EncryptionKeys table (CreatedAt, UpdatedAt)\nUPDATE \"EncryptionKeys\" SET \"CreatedAt\" =\n CASE\n WHEN \"CreatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9] [0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9][0-9][0-9]'\n THEN \"CreatedAt\"\n WHEN \"CreatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]T[0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9]*'\n THEN substr(\"CreatedAt\", 1, 10) || ' ' || substr(\"CreatedAt\", 12, 12)\n WHEN \"CreatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9][T ][0-9][0-9]:[0-9][0-9]:[0-9][0-9]*'\n THEN substr(\"CreatedAt\", 1, 10) || ' ' || substr(replace(\"CreatedAt\", 'T', ' '), 12, 8) || '.000'\n ELSE \"CreatedAt\"\n END;\n\nUPDATE \"EncryptionKeys\" SET \"UpdatedAt\" =\n CASE\n WHEN \"UpdatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9] [0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9][0-9][0-9]'\n THEN \"UpdatedAt\"\n WHEN \"UpdatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]T[0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9]*'\n THEN substr(\"UpdatedAt\", 1, 10) || ' ' || substr(\"UpdatedAt\", 12, 12)\n WHEN \"UpdatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9][T ][0-9][0-9]:[0-9][0-9]:[0-9][0-9]*'\n THEN substr(\"UpdatedAt\", 1, 10) || ' ' || substr(replace(\"UpdatedAt\", 'T', ' '), 12, 8) || '.000'\n ELSE \"UpdatedAt\"\n END;\n\n-- Update Settings table (CreatedAt, UpdatedAt)\nUPDATE \"Settings\" SET \"CreatedAt\" =\n CASE\n WHEN \"CreatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9] [0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9][0-9][0-9]'\n THEN \"CreatedAt\"\n WHEN \"CreatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]T[0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9]*'\n THEN substr(\"CreatedAt\", 1, 10) || ' ' || substr(\"CreatedAt\", 12, 12)\n WHEN \"CreatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9][T ][0-9][0-9]:[0-9][0-9]:[0-9][0-9]*'\n THEN substr(\"CreatedAt\", 1, 10) || ' ' || substr(replace(\"CreatedAt\", 'T', ' '), 12, 8) || '.000'\n ELSE \"CreatedAt\"\n END;\n\nUPDATE \"Settings\" SET \"UpdatedAt\" =\n CASE\n WHEN \"UpdatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9] [0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9][0-9][0-9]'\n THEN \"UpdatedAt\"\n WHEN \"UpdatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]T[0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9]*'\n THEN substr(\"UpdatedAt\", 1, 10) || ' ' || substr(\"UpdatedAt\", 12, 12)\n WHEN \"UpdatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9][T ][0-9][0-9]:[0-9][0-9]:[0-9][0-9]*'\n THEN substr(\"UpdatedAt\", 1, 10) || ' ' || substr(replace(\"UpdatedAt\", 'T', ' '), 12, 8) || '.000'\n ELSE \"UpdatedAt\"\n END;\n\n-- Update Credentials table (CreatedAt, UpdatedAt)\nUPDATE \"Credentials\" SET \"CreatedAt\" =\n CASE\n WHEN \"CreatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9] [0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9][0-9][0-9]'\n THEN \"CreatedAt\"\n WHEN \"CreatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]T[0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9]*'\n THEN substr(\"CreatedAt\", 1, 10) || ' ' || substr(\"CreatedAt\", 12, 12)\n WHEN \"CreatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9][T ][0-9][0-9]:[0-9][0-9]:[0-9][0-9]*'\n THEN substr(\"CreatedAt\", 1, 10) || ' ' || substr(replace(\"CreatedAt\", 'T', ' '), 12, 8) || '.000'\n ELSE \"CreatedAt\"\n END;\n\nUPDATE \"Credentials\" SET \"UpdatedAt\" =\n CASE\n WHEN \"UpdatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9] [0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9][0-9][0-9]'\n THEN \"UpdatedAt\"\n WHEN \"UpdatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]T[0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9]*'\n THEN substr(\"UpdatedAt\", 1, 10) || ' ' || substr(\"UpdatedAt\", 12, 12)\n WHEN \"UpdatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9][T ][0-9][0-9]:[0-9][0-9]:[0-9][0-9]*'\n THEN substr(\"UpdatedAt\", 1, 10) || ' ' || substr(replace(\"UpdatedAt\", 'T', ' '), 12, 8) || '.000'\n ELSE \"UpdatedAt\"\n END;\n\n-- Update Attachments table (CreatedAt, UpdatedAt)\nUPDATE \"Attachments\" SET \"CreatedAt\" =\n CASE\n WHEN \"CreatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9] [0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9][0-9][0-9]'\n THEN \"CreatedAt\"\n WHEN \"CreatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]T[0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9]*'\n THEN substr(\"CreatedAt\", 1, 10) || ' ' || substr(\"CreatedAt\", 12, 12)\n WHEN \"CreatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9][T ][0-9][0-9]:[0-9][0-9]:[0-9][0-9]*'\n THEN substr(\"CreatedAt\", 1, 10) || ' ' || substr(replace(\"CreatedAt\", 'T', ' '), 12, 8) || '.000'\n ELSE \"CreatedAt\"\n END;\n\nUPDATE \"Attachments\" SET \"UpdatedAt\" =\n CASE\n WHEN \"UpdatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9] [0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9][0-9][0-9]'\n THEN \"UpdatedAt\"\n WHEN \"UpdatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]T[0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9]*'\n THEN substr(\"UpdatedAt\", 1, 10) || ' ' || substr(\"UpdatedAt\", 12, 12)\n WHEN \"UpdatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9][T ][0-9][0-9]:[0-9][0-9]:[0-9][0-9]*'\n THEN substr(\"UpdatedAt\", 1, 10) || ' ' || substr(replace(\"UpdatedAt\", 'T', ' '), 12, 8) || '.000'\n ELSE \"UpdatedAt\"\n END;\n\n-- Update Passwords table (CreatedAt, UpdatedAt)\nUPDATE \"Passwords\" SET \"CreatedAt\" =\n CASE\n WHEN \"CreatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9] [0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9][0-9][0-9]'\n THEN \"CreatedAt\"\n WHEN \"CreatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]T[0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9]*'\n THEN substr(\"CreatedAt\", 1, 10) || ' ' || substr(\"CreatedAt\", 12, 12)\n WHEN \"CreatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9][T ][0-9][0-9]:[0-9][0-9]:[0-9][0-9]*'\n THEN substr(\"CreatedAt\", 1, 10) || ' ' || substr(replace(\"CreatedAt\", 'T', ' '), 12, 8) || '.000'\n ELSE \"CreatedAt\"\n END;\n\nUPDATE \"Passwords\" SET \"UpdatedAt\" =\n CASE\n WHEN \"UpdatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9] [0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9][0-9][0-9]'\n THEN \"UpdatedAt\"\n WHEN \"UpdatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]T[0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9]*'\n THEN substr(\"UpdatedAt\", 1, 10) || ' ' || substr(\"UpdatedAt\", 12, 12)\n WHEN \"UpdatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9][T ][0-9][0-9]:[0-9][0-9]:[0-9][0-9]*'\n THEN substr(\"UpdatedAt\", 1, 10) || ' ' || substr(replace(\"UpdatedAt\", 'T', ' '), 12, 8) || '.000'\n ELSE \"UpdatedAt\"\n END;\n\n-- Update TotpCodes table (CreatedAt, UpdatedAt)\nUPDATE \"TotpCodes\" SET \"CreatedAt\" =\n CASE\n WHEN \"CreatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9] [0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9][0-9][0-9]'\n THEN \"CreatedAt\"\n WHEN \"CreatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]T[0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9]*'\n THEN substr(\"CreatedAt\", 1, 10) || ' ' || substr(\"CreatedAt\", 12, 12)\n WHEN \"CreatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9][T ][0-9][0-9]:[0-9][0-9]:[0-9][0-9]*'\n THEN substr(\"CreatedAt\", 1, 10) || ' ' || substr(replace(\"CreatedAt\", 'T', ' '), 12, 8) || '.000'\n ELSE \"CreatedAt\"\n END;\n\nUPDATE \"TotpCodes\" SET \"UpdatedAt\" =\n CASE\n WHEN \"UpdatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9] [0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9][0-9][0-9]'\n THEN \"UpdatedAt\"\n WHEN \"UpdatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]T[0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9]*'\n THEN substr(\"UpdatedAt\", 1, 10) || ' ' || substr(\"UpdatedAt\", 12, 12)\n WHEN \"UpdatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9][T ][0-9][0-9]:[0-9][0-9]:[0-9][0-9]*'\n THEN substr(\"UpdatedAt\", 1, 10) || ' ' || substr(replace(\"UpdatedAt\", 'T', ' '), 12, 8) || '.000'\n ELSE \"UpdatedAt\"\n END;\n\n-- =====================================================================================\n-- End of Date Format Normalization Migration\n-- =====================================================================================\n\n-- Recreate indexes\nCREATE INDEX \"IX_Credentials_AliasId\" ON \"Credentials\" (\"AliasId\");\nCREATE INDEX \"IX_Credentials_ServiceId\" ON \"Credentials\" (\"ServiceId\");\nCREATE INDEX \"IX_Attachments_CredentialId\" ON \"Attachments\" (\"CredentialId\");\nCREATE INDEX \"IX_Passwords_CredentialId\" ON \"Passwords\" (\"CredentialId\");\nCREATE INDEX \"IX_TotpCodes_CredentialId\" ON \"TotpCodes\" (\"CredentialId\");\n\n-- Clean up temp tables\nDROP TABLE \"__EFMigrationsHistory_temp\";\nDROP TABLE \"Aliases_temp\";\nDROP TABLE \"Services_temp\";\nDROP TABLE \"EncryptionKeys_temp\";\nDROP TABLE \"Settings_temp\";\nDROP TABLE \"Credentials_temp\";\nDROP TABLE \"Attachments_temp\";\nDROP TABLE \"Passwords_temp\";\nDROP TABLE \"TotpCodes_temp\";\n\nPRAGMA foreign_keys = ON;\n\n\nCREATE TABLE \"Passkeys\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_Passkeys\" PRIMARY KEY,\n \"RpId\" TEXT COLLATE NOCASE NOT NULL,\n \"UserHandle\" BLOB NOT NULL,\n \"PublicKey\" TEXT NOT NULL,\n \"PrivateKey\" TEXT NOT NULL,\n \"PrfKey\" BLOB NULL,\n \"DisplayName\" TEXT NOT NULL,\n \"AdditionalData\" BLOB NULL,\n \"CredentialId\" TEXT NOT NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"UpdatedAt\" TEXT NOT NULL,\n \"IsDeleted\" INTEGER NOT NULL,\n CONSTRAINT \"FK_Passkeys_Credentials_CredentialId\" FOREIGN KEY (\"CredentialId\") REFERENCES \"Credentials\" (\"Id\") ON DELETE CASCADE\n);\n\nCREATE INDEX \"IX_Passkeys_CredentialId\" ON \"Passkeys\" (\"CredentialId\");\n\nCREATE INDEX \"IX_Passkeys_RpId\" ON \"Passkeys\" (\"RpId\");\n\nINSERT INTO \"__EFMigrationsHistory\" (\"MigrationId\", \"ProductVersion\")\nVALUES ('20251014122838_1.6.0-AddPasskeys', '9.0.4');\n\nALTER TABLE \"TotpCodes\" RENAME COLUMN \"CredentialId\" TO \"ItemId\";\n\nDROP INDEX IF EXISTS \"IX_TotpCodes_CredentialId\";\n\nCREATE INDEX IF NOT EXISTS \"IX_TotpCodes_ItemId\" ON \"TotpCodes\" (\"ItemId\");\n\nALTER TABLE \"Passkeys\" RENAME COLUMN \"CredentialId\" TO \"ItemId\";\n\nDROP INDEX IF EXISTS \"IX_Passkeys_CredentialId\";\n\nCREATE INDEX IF NOT EXISTS \"IX_Passkeys_ItemId\" ON \"Passkeys\" (\"ItemId\");\n\nALTER TABLE \"Attachments\" RENAME COLUMN \"CredentialId\" TO \"ItemId\";\n\nDROP INDEX IF EXISTS \"IX_Attachments_CredentialId\";\n\nCREATE INDEX IF NOT EXISTS \"IX_Attachments_ItemId\" ON \"Attachments\" (\"ItemId\");\n\nCREATE TABLE \"FieldDefinitions\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_FieldDefinitions\" PRIMARY KEY,\n \"FieldType\" TEXT NOT NULL,\n \"Label\" TEXT NOT NULL,\n \"IsMultiValue\" INTEGER NOT NULL,\n \"IsHidden\" INTEGER NOT NULL,\n \"EnableHistory\" INTEGER NOT NULL,\n \"Weight\" INTEGER NOT NULL,\n \"ApplicableToTypes\" TEXT NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"UpdatedAt\" TEXT NOT NULL,\n \"IsDeleted\" INTEGER NOT NULL\n);\n\nCREATE TABLE \"Folders\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_Folders\" PRIMARY KEY,\n \"Name\" TEXT NOT NULL,\n \"ParentFolderId\" TEXT NULL,\n \"Weight\" INTEGER NOT NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"UpdatedAt\" TEXT NOT NULL,\n \"IsDeleted\" INTEGER NOT NULL,\n CONSTRAINT \"FK_Folders_Folders_ParentFolderId\" FOREIGN KEY (\"ParentFolderId\") REFERENCES \"Folders\" (\"Id\") ON DELETE CASCADE\n);\n\nCREATE TABLE \"Logos\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_Logos\" PRIMARY KEY,\n \"Source\" TEXT NOT NULL,\n \"FileData\" BLOB NULL,\n \"MimeType\" TEXT NULL,\n \"FetchedAt\" TEXT NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"UpdatedAt\" TEXT NOT NULL,\n \"IsDeleted\" INTEGER NOT NULL\n);\n\nCREATE TABLE \"Tags\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_Tags\" PRIMARY KEY,\n \"Name\" TEXT NOT NULL,\n \"Color\" TEXT NULL,\n \"DisplayOrder\" INTEGER NOT NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"UpdatedAt\" TEXT NOT NULL,\n \"IsDeleted\" INTEGER NOT NULL\n);\n\nCREATE TABLE \"Items\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_Items\" PRIMARY KEY,\n \"Name\" TEXT NULL,\n \"ItemType\" TEXT NOT NULL,\n \"LogoId\" TEXT NULL,\n \"DeletedAt\" TEXT NULL,\n \"FolderId\" TEXT NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"UpdatedAt\" TEXT NOT NULL,\n \"IsDeleted\" INTEGER NOT NULL,\n CONSTRAINT \"FK_Items_Folders_FolderId\" FOREIGN KEY (\"FolderId\") REFERENCES \"Folders\" (\"Id\") ON DELETE SET NULL,\n CONSTRAINT \"FK_Items_Logos_LogoId\" FOREIGN KEY (\"LogoId\") REFERENCES \"Logos\" (\"Id\") ON DELETE SET NULL\n);\n\nCREATE TABLE \"FieldHistories\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_FieldHistories\" PRIMARY KEY,\n \"ItemId\" TEXT NOT NULL,\n \"FieldDefinitionId\" TEXT NULL,\n \"FieldKey\" TEXT NULL,\n \"ValueSnapshot\" TEXT NOT NULL,\n \"ChangedAt\" TEXT NOT NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"UpdatedAt\" TEXT NOT NULL,\n \"IsDeleted\" INTEGER NOT NULL,\n CONSTRAINT \"FK_FieldHistories_FieldDefinitions_FieldDefinitionId\" FOREIGN KEY (\"FieldDefinitionId\") REFERENCES \"FieldDefinitions\" (\"Id\") ON DELETE CASCADE,\n CONSTRAINT \"FK_FieldHistories_Items_ItemId\" FOREIGN KEY (\"ItemId\") REFERENCES \"Items\" (\"Id\") ON DELETE CASCADE\n);\n\nCREATE TABLE \"FieldValues\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_FieldValues\" PRIMARY KEY,\n \"ItemId\" TEXT NOT NULL,\n \"FieldDefinitionId\" TEXT NULL,\n \"FieldKey\" TEXT NULL,\n \"Value\" TEXT NULL,\n \"Weight\" INTEGER NOT NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"UpdatedAt\" TEXT NOT NULL,\n \"IsDeleted\" INTEGER NOT NULL,\n CONSTRAINT \"FK_FieldValues_FieldDefinitions_FieldDefinitionId\" FOREIGN KEY (\"FieldDefinitionId\") REFERENCES \"FieldDefinitions\" (\"Id\") ON DELETE CASCADE,\n CONSTRAINT \"FK_FieldValues_Items_ItemId\" FOREIGN KEY (\"ItemId\") REFERENCES \"Items\" (\"Id\") ON DELETE CASCADE\n);\n\nCREATE TABLE \"ItemTags\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_ItemTags\" PRIMARY KEY,\n \"ItemId\" TEXT NOT NULL,\n \"TagId\" TEXT NOT NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"UpdatedAt\" TEXT NOT NULL,\n \"IsDeleted\" INTEGER NOT NULL,\n CONSTRAINT \"FK_ItemTags_Items_ItemId\" FOREIGN KEY (\"ItemId\") REFERENCES \"Items\" (\"Id\") ON DELETE CASCADE,\n CONSTRAINT \"FK_ItemTags_Tags_TagId\" FOREIGN KEY (\"TagId\") REFERENCES \"Tags\" (\"Id\") ON DELETE CASCADE\n);\n\nCREATE INDEX \"IX_FieldHistories_FieldDefinitionId\" ON \"FieldHistories\" (\"FieldDefinitionId\");\n\nCREATE INDEX \"IX_FieldHistories_ItemId\" ON \"FieldHistories\" (\"ItemId\");\n\nCREATE INDEX \"IX_FieldValues_FieldDefinitionId\" ON \"FieldValues\" (\"FieldDefinitionId\");\n\nCREATE INDEX \"IX_FieldValues_FieldKey\" ON \"FieldValues\" (\"FieldKey\");\n\nCREATE INDEX \"IX_FieldValues_ItemId\" ON \"FieldValues\" (\"ItemId\");\n\nCREATE INDEX \"IX_FieldValues_ItemId_FieldDefinitionId_Weight\" ON \"FieldValues\" (\"ItemId\", \"FieldDefinitionId\", \"Weight\");\n\nCREATE INDEX \"IX_FieldValues_ItemId_FieldKey\" ON \"FieldValues\" (\"ItemId\", \"FieldKey\");\n\nCREATE INDEX \"IX_Folders_ParentFolderId\" ON \"Folders\" (\"ParentFolderId\");\n\nCREATE INDEX \"IX_Items_FolderId\" ON \"Items\" (\"FolderId\");\n\nCREATE INDEX \"IX_Items_LogoId\" ON \"Items\" (\"LogoId\");\n\nCREATE INDEX \"IX_ItemTags_ItemId\" ON \"ItemTags\" (\"ItemId\");\n\nCREATE UNIQUE INDEX \"IX_ItemTags_ItemId_TagId\" ON \"ItemTags\" (\"ItemId\", \"TagId\");\n\nCREATE INDEX \"IX_ItemTags_TagId\" ON \"ItemTags\" (\"TagId\");\n\nCREATE UNIQUE INDEX \"IX_Logos_Source\" ON \"Logos\" (\"Source\");\n\nCREATE INDEX \"IX_Tags_Name\" ON \"Tags\" (\"Name\");\n\n\n INSERT INTO Items (Id, Name, ItemType, LogoId, FolderId, CreatedAt, UpdatedAt, IsDeleted)\n SELECT\n c.Id,\n s.Name AS Name,\n CASE\n WHEN a.Id IS NOT NULL AND (\n (a.FirstName IS NOT NULL AND a.FirstName != '') OR\n (a.LastName IS NOT NULL AND a.LastName != '') OR\n (a.Gender IS NOT NULL AND a.Gender != '') OR\n (a.BirthDate IS NOT NULL AND a.BirthDate != '' AND a.BirthDate NOT LIKE '0001-%')\n ) THEN 'Alias'\n ELSE 'Login'\n END AS ItemType,\n NULL AS LogoId,\n NULL AS FolderId,\n c.CreatedAt,\n c.UpdatedAt,\n c.IsDeleted\n FROM Credentials c\n LEFT JOIN Services s ON s.Id = c.ServiceId\n LEFT JOIN Aliases a ON a.Id = c.AliasId;\n \n\n\n INSERT INTO Logos (Id, Source, FileData, MimeType, FetchedAt, CreatedAt, UpdatedAt, IsDeleted)\n SELECT\n UPPER(SUBSTR(hex(randomblob(4)), 1, 8) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(6)), 1, 12)) AS Id,\n -- Extract and normalize hostname: remove protocol, path, lowercase, and www. prefix\n REPLACE(\n LOWER(\n SUBSTR(\n CASE\n WHEN s.Url LIKE 'https://%' THEN SUBSTR(s.Url, 9)\n WHEN s.Url LIKE 'http://%' THEN SUBSTR(s.Url, 8)\n ELSE s.Url\n END,\n 1,\n CASE\n WHEN INSTR(\n CASE\n WHEN s.Url LIKE 'https://%' THEN SUBSTR(s.Url, 9)\n WHEN s.Url LIKE 'http://%' THEN SUBSTR(s.Url, 8)\n ELSE s.Url\n END, '/') > 0\n THEN INSTR(\n CASE\n WHEN s.Url LIKE 'https://%' THEN SUBSTR(s.Url, 9)\n WHEN s.Url LIKE 'http://%' THEN SUBSTR(s.Url, 8)\n ELSE s.Url\n END, '/') - 1\n ELSE LENGTH(\n CASE\n WHEN s.Url LIKE 'https://%' THEN SUBSTR(s.Url, 9)\n WHEN s.Url LIKE 'http://%' THEN SUBSTR(s.Url, 8)\n ELSE s.Url\n END)\n END\n )\n ),\n 'www.', ''\n ) AS Source,\n s.Logo AS FileData,\n 'image/png' AS MimeType,\n NULL AS FetchedAt,\n MIN(s.CreatedAt) AS CreatedAt,\n MAX(s.UpdatedAt) AS UpdatedAt,\n 0 AS IsDeleted\n FROM Services s\n WHERE s.Logo IS NOT NULL AND s.Url IS NOT NULL AND s.Url != ''\n GROUP BY REPLACE(\n LOWER(\n SUBSTR(\n CASE\n WHEN s.Url LIKE 'https://%' THEN SUBSTR(s.Url, 9)\n WHEN s.Url LIKE 'http://%' THEN SUBSTR(s.Url, 8)\n ELSE s.Url\n END,\n 1,\n CASE\n WHEN INSTR(\n CASE\n WHEN s.Url LIKE 'https://%' THEN SUBSTR(s.Url, 9)\n WHEN s.Url LIKE 'http://%' THEN SUBSTR(s.Url, 8)\n ELSE s.Url\n END, '/') > 0\n THEN INSTR(\n CASE\n WHEN s.Url LIKE 'https://%' THEN SUBSTR(s.Url, 9)\n WHEN s.Url LIKE 'http://%' THEN SUBSTR(s.Url, 8)\n ELSE s.Url\n END, '/') - 1\n ELSE LENGTH(\n CASE\n WHEN s.Url LIKE 'https://%' THEN SUBSTR(s.Url, 9)\n WHEN s.Url LIKE 'http://%' THEN SUBSTR(s.Url, 8)\n ELSE s.Url\n END)\n END\n )\n ),\n 'www.', ''\n );\n \n\n\n UPDATE Items\n SET LogoId = (\n SELECT l.Id FROM Logos l\n INNER JOIN Services s ON REPLACE(\n LOWER(\n SUBSTR(\n CASE\n WHEN s.Url LIKE 'https://%' THEN SUBSTR(s.Url, 9)\n WHEN s.Url LIKE 'http://%' THEN SUBSTR(s.Url, 8)\n ELSE s.Url\n END,\n 1,\n CASE\n WHEN INSTR(\n CASE\n WHEN s.Url LIKE 'https://%' THEN SUBSTR(s.Url, 9)\n WHEN s.Url LIKE 'http://%' THEN SUBSTR(s.Url, 8)\n ELSE s.Url\n END, '/') > 0\n THEN INSTR(\n CASE\n WHEN s.Url LIKE 'https://%' THEN SUBSTR(s.Url, 9)\n WHEN s.Url LIKE 'http://%' THEN SUBSTR(s.Url, 8)\n ELSE s.Url\n END, '/') - 1\n ELSE LENGTH(\n CASE\n WHEN s.Url LIKE 'https://%' THEN SUBSTR(s.Url, 9)\n WHEN s.Url LIKE 'http://%' THEN SUBSTR(s.Url, 8)\n ELSE s.Url\n END)\n END\n )\n ),\n 'www.', ''\n ) = l.Source\n INNER JOIN Credentials c ON c.ServiceId = s.Id\n WHERE c.Id = Items.Id\n LIMIT 1\n )\n WHERE EXISTS (\n SELECT 1 FROM Credentials c\n INNER JOIN Services s ON s.Id = c.ServiceId\n WHERE c.Id = Items.Id AND s.Logo IS NOT NULL\n );\n \n\n\n INSERT INTO FieldValues (Id, ItemId, FieldDefinitionId, FieldKey, Value, Weight, CreatedAt, UpdatedAt, IsDeleted)\n SELECT\n UPPER(SUBSTR(hex(randomblob(4)), 1, 8) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(6)), 1, 12)) AS Id,\n c.Id AS ItemId,\n NULL AS FieldDefinitionId,\n 'login.url' AS FieldKey,\n s.Url AS Value,\n 0 AS Weight,\n s.UpdatedAt AS CreatedAt,\n s.UpdatedAt AS UpdatedAt,\n 0 AS IsDeleted\n FROM Credentials c\n INNER JOIN Services s ON s.Id = c.ServiceId\n WHERE s.Url IS NOT NULL AND s.Url != '';\n \n\n\n INSERT INTO FieldValues (Id, ItemId, FieldDefinitionId, FieldKey, Value, Weight, CreatedAt, UpdatedAt, IsDeleted)\n SELECT\n UPPER(SUBSTR(hex(randomblob(4)), 1, 8) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(6)), 1, 12)) AS Id,\n c.Id AS ItemId,\n NULL AS FieldDefinitionId,\n 'login.username' AS FieldKey,\n c.Username AS Value,\n 0 AS Weight,\n c.UpdatedAt AS CreatedAt,\n c.UpdatedAt AS UpdatedAt,\n 0 AS IsDeleted\n FROM Credentials c\n WHERE c.Username IS NOT NULL AND c.Username != '';\n \n\n\n INSERT INTO FieldValues (Id, ItemId, FieldDefinitionId, FieldKey, Value, Weight, CreatedAt, UpdatedAt, IsDeleted)\n SELECT\n UPPER(SUBSTR(hex(randomblob(4)), 1, 8) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(6)), 1, 12)) AS Id,\n c.Id AS ItemId,\n NULL AS FieldDefinitionId,\n 'login.notes' AS FieldKey,\n c.Notes AS Value,\n 0 AS Weight,\n c.UpdatedAt AS CreatedAt,\n c.UpdatedAt AS UpdatedAt,\n 0 AS IsDeleted\n FROM Credentials c\n WHERE c.Notes IS NOT NULL AND c.Notes != '';\n \n\n\n INSERT INTO FieldValues (Id, ItemId, FieldDefinitionId, FieldKey, Value, Weight, CreatedAt, UpdatedAt, IsDeleted)\n SELECT\n UPPER(SUBSTR(hex(randomblob(4)), 1, 8) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(6)), 1, 12)) AS Id,\n p.CredentialId AS ItemId,\n NULL AS FieldDefinitionId,\n 'login.password' AS FieldKey,\n p.Value AS Value,\n 0 AS Weight,\n p.UpdatedAt AS CreatedAt,\n p.UpdatedAt AS UpdatedAt,\n 0 AS IsDeleted\n FROM Passwords p\n INNER JOIN (\n SELECT CredentialId, MAX(UpdatedAt) AS MaxUpdated, MAX(Id) AS MaxId\n FROM Passwords\n WHERE IsDeleted = 0\n GROUP BY CredentialId\n ) pm ON p.CredentialId = pm.CredentialId AND p.UpdatedAt = pm.MaxUpdated AND p.Id = pm.MaxId\n WHERE p.IsDeleted = 0;\n \n\n\n INSERT INTO FieldValues (Id, ItemId, FieldDefinitionId, FieldKey, Value, Weight, CreatedAt, UpdatedAt, IsDeleted)\n SELECT\n UPPER(SUBSTR(hex(randomblob(4)), 1, 8) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(6)), 1, 12)) AS Id,\n c.Id AS ItemId,\n NULL AS FieldDefinitionId,\n 'login.email' AS FieldKey,\n a.Email AS Value,\n 0 AS Weight,\n a.UpdatedAt AS CreatedAt,\n a.UpdatedAt AS UpdatedAt,\n 0 AS IsDeleted\n FROM Credentials c\n INNER JOIN Aliases a ON a.Id = c.AliasId\n WHERE a.Email IS NOT NULL AND a.Email != '';\n \n\n\n INSERT INTO FieldValues (Id, ItemId, FieldDefinitionId, FieldKey, Value, Weight, CreatedAt, UpdatedAt, IsDeleted)\n SELECT\n UPPER(SUBSTR(hex(randomblob(4)), 1, 8) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(6)), 1, 12)) AS Id,\n c.Id AS ItemId,\n NULL AS FieldDefinitionId,\n 'alias.first_name' AS FieldKey,\n a.FirstName AS Value,\n 0 AS Weight,\n a.UpdatedAt AS CreatedAt,\n a.UpdatedAt AS UpdatedAt,\n 0 AS IsDeleted\n FROM Credentials c\n INNER JOIN Aliases a ON a.Id = c.AliasId\n WHERE a.FirstName IS NOT NULL AND a.FirstName != '';\n \n\n\n INSERT INTO FieldValues (Id, ItemId, FieldDefinitionId, FieldKey, Value, Weight, CreatedAt, UpdatedAt, IsDeleted)\n SELECT\n UPPER(SUBSTR(hex(randomblob(4)), 1, 8) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(6)), 1, 12)) AS Id,\n c.Id AS ItemId,\n NULL AS FieldDefinitionId,\n 'alias.last_name' AS FieldKey,\n a.LastName AS Value,\n 0 AS Weight,\n a.UpdatedAt AS CreatedAt,\n a.UpdatedAt AS UpdatedAt,\n 0 AS IsDeleted\n FROM Credentials c\n INNER JOIN Aliases a ON a.Id = c.AliasId\n WHERE a.LastName IS NOT NULL AND a.LastName != '';\n \n\n\n INSERT INTO FieldValues (Id, ItemId, FieldDefinitionId, FieldKey, Value, Weight, CreatedAt, UpdatedAt, IsDeleted)\n SELECT\n UPPER(SUBSTR(hex(randomblob(4)), 1, 8) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(6)), 1, 12)) AS Id,\n c.Id AS ItemId,\n NULL AS FieldDefinitionId,\n 'alias.gender' AS FieldKey,\n a.Gender AS Value,\n 0 AS Weight,\n a.UpdatedAt AS CreatedAt,\n a.UpdatedAt AS UpdatedAt,\n 0 AS IsDeleted\n FROM Credentials c\n INNER JOIN Aliases a ON a.Id = c.AliasId\n WHERE a.Gender IS NOT NULL AND a.Gender != '';\n \n\n\n INSERT INTO FieldValues (Id, ItemId, FieldDefinitionId, FieldKey, Value, Weight, CreatedAt, UpdatedAt, IsDeleted)\n SELECT\n UPPER(SUBSTR(hex(randomblob(4)), 1, 8) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(6)), 1, 12)) AS Id,\n c.Id AS ItemId,\n NULL AS FieldDefinitionId,\n 'alias.birthdate' AS FieldKey,\n SUBSTR(a.BirthDate, 1, 10) AS Value,\n 0 AS Weight,\n a.UpdatedAt AS CreatedAt,\n a.UpdatedAt AS UpdatedAt,\n 0 AS IsDeleted\n FROM Credentials c\n INNER JOIN Aliases a ON a.Id = c.AliasId\n WHERE a.BirthDate IS NOT NULL AND a.BirthDate != '' AND a.BirthDate NOT LIKE '0001-%';\n \n\nDROP TABLE \"Passwords\";\n\nDROP TABLE \"Credentials\";\n\nDROP TABLE \"Aliases\";\n\nDROP TABLE \"Services\";\n\nCREATE TABLE \"ef_temp_Attachments\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_Attachments\" PRIMARY KEY,\n \"Blob\" BLOB NOT NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"Filename\" TEXT NOT NULL,\n \"IsDeleted\" INTEGER NOT NULL,\n \"ItemId\" TEXT NOT NULL,\n \"UpdatedAt\" TEXT NOT NULL,\n CONSTRAINT \"FK_Attachments_Items_ItemId\" FOREIGN KEY (\"ItemId\") REFERENCES \"Items\" (\"Id\") ON DELETE CASCADE\n);\n\nINSERT INTO \"ef_temp_Attachments\" (\"Id\", \"Blob\", \"CreatedAt\", \"Filename\", \"IsDeleted\", \"ItemId\", \"UpdatedAt\")\nSELECT \"Id\", \"Blob\", \"CreatedAt\", \"Filename\", \"IsDeleted\", \"ItemId\", \"UpdatedAt\"\nFROM \"Attachments\";\n\nCREATE TABLE \"ef_temp_Passkeys\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_Passkeys\" PRIMARY KEY,\n \"AdditionalData\" BLOB NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"DisplayName\" TEXT NOT NULL,\n \"IsDeleted\" INTEGER NOT NULL,\n \"ItemId\" TEXT NOT NULL,\n \"PrfKey\" BLOB NULL,\n \"PrivateKey\" TEXT NOT NULL,\n \"PublicKey\" TEXT NOT NULL,\n \"RpId\" TEXT COLLATE NOCASE NOT NULL,\n \"UpdatedAt\" TEXT NOT NULL,\n \"UserHandle\" BLOB NOT NULL,\n CONSTRAINT \"FK_Passkeys_Items_ItemId\" FOREIGN KEY (\"ItemId\") REFERENCES \"Items\" (\"Id\") ON DELETE CASCADE\n);\n\nINSERT INTO \"ef_temp_Passkeys\" (\"Id\", \"AdditionalData\", \"CreatedAt\", \"DisplayName\", \"IsDeleted\", \"ItemId\", \"PrfKey\", \"PrivateKey\", \"PublicKey\", \"RpId\", \"UpdatedAt\", \"UserHandle\")\nSELECT \"Id\", \"AdditionalData\", \"CreatedAt\", \"DisplayName\", \"IsDeleted\", \"ItemId\", \"PrfKey\", \"PrivateKey\", \"PublicKey\", \"RpId\", \"UpdatedAt\", \"UserHandle\"\nFROM \"Passkeys\";\n\nCREATE TABLE \"ef_temp_TotpCodes\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_TotpCodes\" PRIMARY KEY,\n \"CreatedAt\" TEXT NOT NULL,\n \"IsDeleted\" INTEGER NOT NULL,\n \"ItemId\" TEXT NOT NULL,\n \"Name\" TEXT NOT NULL,\n \"SecretKey\" TEXT NOT NULL,\n \"UpdatedAt\" TEXT NOT NULL,\n CONSTRAINT \"FK_TotpCodes_Items_ItemId\" FOREIGN KEY (\"ItemId\") REFERENCES \"Items\" (\"Id\") ON DELETE CASCADE\n);\n\nINSERT INTO \"ef_temp_TotpCodes\" (\"Id\", \"CreatedAt\", \"IsDeleted\", \"ItemId\", \"Name\", \"SecretKey\", \"UpdatedAt\")\nSELECT \"Id\", \"CreatedAt\", \"IsDeleted\", \"ItemId\", \"Name\", \"SecretKey\", \"UpdatedAt\"\nFROM \"TotpCodes\";\n\nCOMMIT;\n\nPRAGMA foreign_keys = 0;\n\nBEGIN TRANSACTION;\nDROP TABLE \"Attachments\";\n\nALTER TABLE \"ef_temp_Attachments\" RENAME TO \"Attachments\";\n\nDROP TABLE \"Passkeys\";\n\nALTER TABLE \"ef_temp_Passkeys\" RENAME TO \"Passkeys\";\n\nDROP TABLE \"TotpCodes\";\n\nALTER TABLE \"ef_temp_TotpCodes\" RENAME TO \"TotpCodes\";\n\nCOMMIT;\n\nPRAGMA foreign_keys = 1;\n\nBEGIN TRANSACTION;\nCREATE INDEX \"IX_Attachments_ItemId\" ON \"Attachments\" (\"ItemId\");\n\nCREATE INDEX \"IX_Passkeys_ItemId\" ON \"Passkeys\" (\"ItemId\");\n\nCREATE INDEX \"IX_Passkeys_RpId\" ON \"Passkeys\" (\"RpId\");\n\nCREATE INDEX \"IX_TotpCodes_ItemId\" ON \"TotpCodes\" (\"ItemId\");\n\nCOMMIT;\n\nINSERT INTO \"__EFMigrationsHistory\" (\"MigrationId\", \"ProductVersion\")\nVALUES ('20251213111207_1.7.0-FieldBasedDataModelUpdate', '9.0.4');\n"; +declare const COMPLETE_SCHEMA_SQL = "\n\uFEFFCREATE TABLE IF NOT EXISTS \"__EFMigrationsHistory\" (\n \"MigrationId\" TEXT NOT NULL CONSTRAINT \"PK___EFMigrationsHistory\" PRIMARY KEY,\n \"ProductVersion\" TEXT NOT NULL\n);\n\nBEGIN TRANSACTION;\nCREATE TABLE \"Aliases\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_Aliases\" PRIMARY KEY,\n \"Gender\" VARCHAR NULL,\n \"FirstName\" VARCHAR NULL,\n \"LastName\" VARCHAR NULL,\n \"NickName\" VARCHAR NULL,\n \"BirthDate\" TEXT NOT NULL,\n \"AddressStreet\" VARCHAR NULL,\n \"AddressCity\" VARCHAR NULL,\n \"AddressState\" VARCHAR NULL,\n \"AddressZipCode\" VARCHAR NULL,\n \"AddressCountry\" VARCHAR NULL,\n \"Hobbies\" TEXT NULL,\n \"EmailPrefix\" TEXT NULL,\n \"PhoneMobile\" TEXT NULL,\n \"BankAccountIBAN\" TEXT NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"UpdatedAt\" TEXT NOT NULL\n);\n\nCREATE TABLE \"Services\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_Services\" PRIMARY KEY,\n \"Name\" TEXT NULL,\n \"Url\" TEXT NULL,\n \"Logo\" BLOB NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"UpdatedAt\" TEXT NOT NULL\n);\n\nCREATE TABLE \"Credentials\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_Credentials\" PRIMARY KEY,\n \"AliasId\" TEXT NOT NULL,\n \"Notes\" TEXT NULL,\n \"Username\" TEXT NOT NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"UpdatedAt\" TEXT NOT NULL,\n \"ServiceId\" TEXT NOT NULL,\n CONSTRAINT \"FK_Credentials_Aliases_AliasId\" FOREIGN KEY (\"AliasId\") REFERENCES \"Aliases\" (\"Id\") ON DELETE CASCADE,\n CONSTRAINT \"FK_Credentials_Services_ServiceId\" FOREIGN KEY (\"ServiceId\") REFERENCES \"Services\" (\"Id\") ON DELETE CASCADE\n);\n\nCREATE TABLE \"Attachment\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_Attachment\" PRIMARY KEY,\n \"Filename\" TEXT NOT NULL,\n \"Blob\" BLOB NOT NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"UpdatedAt\" TEXT NOT NULL,\n \"CredentialId\" TEXT NOT NULL,\n CONSTRAINT \"FK_Attachment_Credentials_CredentialId\" FOREIGN KEY (\"CredentialId\") REFERENCES \"Credentials\" (\"Id\") ON DELETE CASCADE\n);\n\nCREATE TABLE \"Passwords\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_Passwords\" PRIMARY KEY,\n \"Value\" TEXT NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"UpdatedAt\" TEXT NOT NULL,\n \"CredentialId\" TEXT NOT NULL,\n CONSTRAINT \"FK_Passwords_Credentials_CredentialId\" FOREIGN KEY (\"CredentialId\") REFERENCES \"Credentials\" (\"Id\") ON DELETE CASCADE\n);\n\nCREATE INDEX \"IX_Attachment_CredentialId\" ON \"Attachment\" (\"CredentialId\");\n\nCREATE INDEX \"IX_Credentials_AliasId\" ON \"Credentials\" (\"AliasId\");\n\nCREATE INDEX \"IX_Credentials_ServiceId\" ON \"Credentials\" (\"ServiceId\");\n\nCREATE INDEX \"IX_Passwords_CredentialId\" ON \"Passwords\" (\"CredentialId\");\n\nINSERT INTO \"__EFMigrationsHistory\" (\"MigrationId\", \"ProductVersion\")\nVALUES ('20240708094944_1.0.0-InitialMigration', '9.0.4');\n\nINSERT INTO \"__EFMigrationsHistory\" (\"MigrationId\", \"ProductVersion\")\nVALUES ('20240708224522_1.0.1-EmptyTestMigration', '9.0.4');\n\nALTER TABLE \"Aliases\" RENAME COLUMN \"EmailPrefix\" TO \"Email\";\n\nINSERT INTO \"__EFMigrationsHistory\" (\"MigrationId\", \"ProductVersion\")\nVALUES ('20240711204207_1.0.2-ChangeEmailColumn', '9.0.4');\n\nCREATE TABLE \"EncryptionKeys\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_EncryptionKeys\" PRIMARY KEY,\n \"PublicKey\" TEXT NOT NULL,\n \"PrivateKey\" TEXT NOT NULL,\n \"IsPrimary\" INTEGER NOT NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"UpdatedAt\" TEXT NOT NULL\n);\n\nINSERT INTO \"__EFMigrationsHistory\" (\"MigrationId\", \"ProductVersion\")\nVALUES ('20240729105618_1.1.0-AddPkiTables', '9.0.4');\n\nCREATE TABLE \"Settings\" (\n \"Key\" TEXT NOT NULL CONSTRAINT \"PK_Settings\" PRIMARY KEY,\n \"Value\" TEXT NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"UpdatedAt\" TEXT NOT NULL\n);\n\nINSERT INTO \"__EFMigrationsHistory\" (\"MigrationId\", \"ProductVersion\")\nVALUES ('20240805073413_1.2.0-AddSettingsTable', '9.0.4');\n\nCREATE TABLE \"ef_temp_Aliases\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_Aliases\" PRIMARY KEY,\n \"BirthDate\" TEXT NOT NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"Email\" TEXT NULL,\n \"FirstName\" VARCHAR NULL,\n \"Gender\" VARCHAR NULL,\n \"LastName\" VARCHAR NULL,\n \"NickName\" VARCHAR NULL,\n \"UpdatedAt\" TEXT NOT NULL\n);\n\nINSERT INTO \"ef_temp_Aliases\" (\"Id\", \"BirthDate\", \"CreatedAt\", \"Email\", \"FirstName\", \"Gender\", \"LastName\", \"NickName\", \"UpdatedAt\")\nSELECT \"Id\", \"BirthDate\", \"CreatedAt\", \"Email\", \"FirstName\", \"Gender\", \"LastName\", \"NickName\", \"UpdatedAt\"\nFROM \"Aliases\";\n\nCOMMIT;\n\nPRAGMA foreign_keys = 0;\n\nBEGIN TRANSACTION;\nDROP TABLE \"Aliases\";\n\nALTER TABLE \"ef_temp_Aliases\" RENAME TO \"Aliases\";\n\nCOMMIT;\n\nPRAGMA foreign_keys = 1;\n\nINSERT INTO \"__EFMigrationsHistory\" (\"MigrationId\", \"ProductVersion\")\nVALUES ('20240805122422_1.3.0-UpdateIdentityStructure', '9.0.4');\n\nBEGIN TRANSACTION;\nCREATE TABLE \"ef_temp_Credentials\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_Credentials\" PRIMARY KEY,\n \"AliasId\" TEXT NOT NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"Notes\" TEXT NULL,\n \"ServiceId\" TEXT NOT NULL,\n \"UpdatedAt\" TEXT NOT NULL,\n \"Username\" TEXT NULL,\n CONSTRAINT \"FK_Credentials_Aliases_AliasId\" FOREIGN KEY (\"AliasId\") REFERENCES \"Aliases\" (\"Id\") ON DELETE CASCADE,\n CONSTRAINT \"FK_Credentials_Services_ServiceId\" FOREIGN KEY (\"ServiceId\") REFERENCES \"Services\" (\"Id\") ON DELETE CASCADE\n);\n\nINSERT INTO \"ef_temp_Credentials\" (\"Id\", \"AliasId\", \"CreatedAt\", \"Notes\", \"ServiceId\", \"UpdatedAt\", \"Username\")\nSELECT \"Id\", \"AliasId\", \"CreatedAt\", \"Notes\", \"ServiceId\", \"UpdatedAt\", \"Username\"\nFROM \"Credentials\";\n\nCOMMIT;\n\nPRAGMA foreign_keys = 0;\n\nBEGIN TRANSACTION;\nDROP TABLE \"Credentials\";\n\nALTER TABLE \"ef_temp_Credentials\" RENAME TO \"Credentials\";\n\nCOMMIT;\n\nPRAGMA foreign_keys = 1;\n\nBEGIN TRANSACTION;\nCREATE INDEX \"IX_Credentials_AliasId\" ON \"Credentials\" (\"AliasId\");\n\nCREATE INDEX \"IX_Credentials_ServiceId\" ON \"Credentials\" (\"ServiceId\");\n\nCOMMIT;\n\nINSERT INTO \"__EFMigrationsHistory\" (\"MigrationId\", \"ProductVersion\")\nVALUES ('20240812141727_1.3.1-MakeUsernameOptional', '9.0.4');\n\nBEGIN TRANSACTION;\nALTER TABLE \"Settings\" ADD \"IsDeleted\" INTEGER NOT NULL DEFAULT 0;\n\nALTER TABLE \"Services\" ADD \"IsDeleted\" INTEGER NOT NULL DEFAULT 0;\n\nALTER TABLE \"Passwords\" ADD \"IsDeleted\" INTEGER NOT NULL DEFAULT 0;\n\nALTER TABLE \"EncryptionKeys\" ADD \"IsDeleted\" INTEGER NOT NULL DEFAULT 0;\n\nALTER TABLE \"Credentials\" ADD \"IsDeleted\" INTEGER NOT NULL DEFAULT 0;\n\nALTER TABLE \"Attachment\" ADD \"IsDeleted\" INTEGER NOT NULL DEFAULT 0;\n\nALTER TABLE \"Aliases\" ADD \"IsDeleted\" INTEGER NOT NULL DEFAULT 0;\n\nINSERT INTO \"__EFMigrationsHistory\" (\"MigrationId\", \"ProductVersion\")\nVALUES ('20240916105320_1.4.0-AddSyncSupport', '9.0.4');\n\nALTER TABLE \"Attachment\" RENAME TO \"Attachments\";\n\nCREATE TABLE \"ef_temp_Attachments\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_Attachments\" PRIMARY KEY,\n \"Blob\" BLOB NOT NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"CredentialId\" TEXT NOT NULL,\n \"Filename\" TEXT NOT NULL,\n \"IsDeleted\" INTEGER NOT NULL,\n \"UpdatedAt\" TEXT NOT NULL,\n CONSTRAINT \"FK_Attachments_Credentials_CredentialId\" FOREIGN KEY (\"CredentialId\") REFERENCES \"Credentials\" (\"Id\") ON DELETE CASCADE\n);\n\nINSERT INTO \"ef_temp_Attachments\" (\"Id\", \"Blob\", \"CreatedAt\", \"CredentialId\", \"Filename\", \"IsDeleted\", \"UpdatedAt\")\nSELECT \"Id\", \"Blob\", \"CreatedAt\", \"CredentialId\", \"Filename\", \"IsDeleted\", \"UpdatedAt\"\nFROM \"Attachments\";\n\nCOMMIT;\n\nPRAGMA foreign_keys = 0;\n\nBEGIN TRANSACTION;\nDROP TABLE \"Attachments\";\n\nALTER TABLE \"ef_temp_Attachments\" RENAME TO \"Attachments\";\n\nCOMMIT;\n\nPRAGMA foreign_keys = 1;\n\nBEGIN TRANSACTION;\nCREATE INDEX \"IX_Attachments_CredentialId\" ON \"Attachments\" (\"CredentialId\");\n\nCOMMIT;\n\nINSERT INTO \"__EFMigrationsHistory\" (\"MigrationId\", \"ProductVersion\")\nVALUES ('20240917191243_1.4.1-RenameAttachmentsPlural', '9.0.4');\n\nBEGIN TRANSACTION;\nCREATE TABLE \"TotpCodes\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_TotpCodes\" PRIMARY KEY,\n \"Name\" TEXT NOT NULL,\n \"SecretKey\" TEXT NOT NULL,\n \"CredentialId\" TEXT NOT NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"UpdatedAt\" TEXT NOT NULL,\n \"IsDeleted\" INTEGER NOT NULL,\n CONSTRAINT \"FK_TotpCodes_Credentials_CredentialId\" FOREIGN KEY (\"CredentialId\") REFERENCES \"Credentials\" (\"Id\") ON DELETE CASCADE\n);\n\nCREATE INDEX \"IX_TotpCodes_CredentialId\" ON \"TotpCodes\" (\"CredentialId\");\n\nINSERT INTO \"__EFMigrationsHistory\" (\"MigrationId\", \"ProductVersion\")\nVALUES ('20250310131554_1.5.0-AddTotpCodes', '9.0.4');\n\n\nPRAGMA foreign_keys = OFF;\n\n-- Clean up any existing temp tables first\nDROP TABLE IF EXISTS \"__EFMigrationsHistory_temp\";\nDROP TABLE IF EXISTS \"Aliases_temp\";\nDROP TABLE IF EXISTS \"Services_temp\";\nDROP TABLE IF EXISTS \"EncryptionKeys_temp\";\nDROP TABLE IF EXISTS \"Settings_temp\";\nDROP TABLE IF EXISTS \"Credentials_temp\";\nDROP TABLE IF EXISTS \"Attachments_temp\";\nDROP TABLE IF EXISTS \"Passwords_temp\";\nDROP TABLE IF EXISTS \"TotpCodes_temp\";\n\n-- Create backup tables for all data\nCREATE TABLE \"__EFMigrationsHistory_temp\" AS SELECT * FROM \"__EFMigrationsHistory\";\nCREATE TABLE \"Aliases_temp\" AS SELECT * FROM \"Aliases\";\nCREATE TABLE \"Services_temp\" AS SELECT * FROM \"Services\";\nCREATE TABLE \"EncryptionKeys_temp\" AS SELECT * FROM \"EncryptionKeys\";\nCREATE TABLE \"Settings_temp\" AS SELECT * FROM \"Settings\";\nCREATE TABLE \"Credentials_temp\" AS SELECT * FROM \"Credentials\";\nCREATE TABLE \"Attachments_temp\" AS SELECT * FROM \"Attachments\";\nCREATE TABLE \"Passwords_temp\" AS SELECT * FROM \"Passwords\";\nCREATE TABLE \"TotpCodes_temp\" AS SELECT * FROM \"TotpCodes\";\n\n-- Delete orphaned records that do not have a valid FK to the credential object\nDELETE FROM \"Attachments_temp\" WHERE \"CredentialId\" NOT IN (SELECT \"Id\" FROM \"Credentials_temp\");\nDELETE FROM \"Passwords_temp\" WHERE \"CredentialId\" NOT IN (SELECT \"Id\" FROM \"Credentials_temp\");\nDELETE FROM \"TotpCodes_temp\" WHERE \"CredentialId\" NOT IN (SELECT \"Id\" FROM \"Credentials_temp\");\n\n-- Delete orphaned credentials that do not have valid FKs to alias or service objects\nDELETE FROM \"Credentials_temp\" WHERE \"AliasId\" NOT IN (SELECT \"Id\" FROM \"Aliases_temp\");\nDELETE FROM \"Credentials_temp\" WHERE \"ServiceId\" NOT IN (SELECT \"Id\" FROM \"Services_temp\");\n\n-- After cleaning credentials, clean dependent tables again in case we removed credentials\nDELETE FROM \"Attachments_temp\" WHERE \"CredentialId\" NOT IN (SELECT \"Id\" FROM \"Credentials_temp\");\nDELETE FROM \"Passwords_temp\" WHERE \"CredentialId\" NOT IN (SELECT \"Id\" FROM \"Credentials_temp\");\nDELETE FROM \"TotpCodes_temp\" WHERE \"CredentialId\" NOT IN (SELECT \"Id\" FROM \"Credentials_temp\");\n\n-- Drop all existing tables\nDROP TABLE \"TotpCodes\";\nDROP TABLE \"Passwords\";\nDROP TABLE \"Attachments\";\nDROP TABLE \"Credentials\";\nDROP TABLE \"Settings\";\nDROP TABLE \"EncryptionKeys\";\nDROP TABLE \"Services\";\nDROP TABLE \"Aliases\";\nDROP TABLE \"__EFMigrationsHistory\";\n\n-- Recreate tables with proper constraints (no dependencies first)\nCREATE TABLE \"__EFMigrationsHistory\" (\n \"MigrationId\" TEXT NOT NULL CONSTRAINT \"PK___EFMigrationsHistory\" PRIMARY KEY,\n \"ProductVersion\" TEXT NOT NULL\n);\n\nCREATE TABLE \"Aliases\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_Aliases\" PRIMARY KEY,\n \"BirthDate\" TEXT NOT NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"Email\" TEXT NULL,\n \"FirstName\" VARCHAR NULL,\n \"Gender\" VARCHAR NULL,\n \"LastName\" VARCHAR NULL,\n \"NickName\" VARCHAR NULL,\n \"UpdatedAt\" TEXT NOT NULL,\n \"IsDeleted\" INTEGER NOT NULL DEFAULT 0\n);\n\nCREATE TABLE \"Services\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_Services\" PRIMARY KEY,\n \"Name\" TEXT NULL,\n \"Url\" TEXT NULL,\n \"Logo\" BLOB NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"UpdatedAt\" TEXT NOT NULL,\n \"IsDeleted\" INTEGER NOT NULL DEFAULT 0\n);\n\nCREATE TABLE \"EncryptionKeys\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_EncryptionKeys\" PRIMARY KEY,\n \"PublicKey\" TEXT NOT NULL,\n \"PrivateKey\" TEXT NOT NULL,\n \"IsPrimary\" INTEGER NOT NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"UpdatedAt\" TEXT NOT NULL,\n \"IsDeleted\" INTEGER NOT NULL DEFAULT 0\n);\n\nCREATE TABLE \"Settings\" (\n \"Key\" TEXT NOT NULL CONSTRAINT \"PK_Settings\" PRIMARY KEY,\n \"Value\" TEXT NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"UpdatedAt\" TEXT NOT NULL,\n \"IsDeleted\" INTEGER NOT NULL DEFAULT 0\n);\n\n-- Tables with foreign keys\nCREATE TABLE \"Credentials\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_Credentials\" PRIMARY KEY,\n \"AliasId\" TEXT NOT NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"Notes\" TEXT NULL,\n \"ServiceId\" TEXT NOT NULL,\n \"UpdatedAt\" TEXT NOT NULL,\n \"Username\" TEXT NULL,\n \"IsDeleted\" INTEGER NOT NULL DEFAULT 0,\n CONSTRAINT \"FK_Credentials_Aliases_AliasId\" FOREIGN KEY (\"AliasId\") REFERENCES \"Aliases\" (\"Id\") ON DELETE CASCADE,\n CONSTRAINT \"FK_Credentials_Services_ServiceId\" FOREIGN KEY (\"ServiceId\") REFERENCES \"Services\" (\"Id\") ON DELETE CASCADE\n);\n\nCREATE TABLE \"Attachments\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_Attachments\" PRIMARY KEY,\n \"Blob\" BLOB NOT NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"CredentialId\" TEXT NOT NULL,\n \"Filename\" TEXT NOT NULL,\n \"IsDeleted\" INTEGER NOT NULL DEFAULT 0,\n \"UpdatedAt\" TEXT NOT NULL,\n CONSTRAINT \"FK_Attachments_Credentials_CredentialId\" FOREIGN KEY (\"CredentialId\") REFERENCES \"Credentials\" (\"Id\") ON DELETE CASCADE\n);\n\nCREATE TABLE \"Passwords\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_Passwords\" PRIMARY KEY,\n \"Value\" TEXT NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"UpdatedAt\" TEXT NOT NULL,\n \"CredentialId\" TEXT NOT NULL,\n \"IsDeleted\" INTEGER NOT NULL DEFAULT 0,\n CONSTRAINT \"FK_Passwords_Credentials_CredentialId\" FOREIGN KEY (\"CredentialId\") REFERENCES \"Credentials\" (\"Id\") ON DELETE CASCADE\n);\n\nCREATE TABLE \"TotpCodes\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_TotpCodes\" PRIMARY KEY,\n \"Name\" TEXT NOT NULL,\n \"SecretKey\" TEXT NOT NULL,\n \"CredentialId\" TEXT NOT NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"UpdatedAt\" TEXT NOT NULL,\n \"IsDeleted\" INTEGER NOT NULL DEFAULT 0,\n CONSTRAINT \"FK_TotpCodes_Credentials_CredentialId\" FOREIGN KEY (\"CredentialId\") REFERENCES \"Credentials\" (\"Id\") ON DELETE CASCADE\n);\n\n\n-- Restore data from temp tables\nINSERT INTO \"__EFMigrationsHistory\" SELECT * FROM \"__EFMigrationsHistory_temp\";\nINSERT INTO \"Aliases\" SELECT * FROM \"Aliases_temp\";\nINSERT INTO \"Services\" SELECT * FROM \"Services_temp\";\nINSERT INTO \"EncryptionKeys\" SELECT * FROM \"EncryptionKeys_temp\";\nINSERT INTO \"Settings\" SELECT * FROM \"Settings_temp\";\nINSERT INTO \"Credentials\" SELECT * FROM \"Credentials_temp\";\nINSERT INTO \"Attachments\" SELECT * FROM \"Attachments_temp\";\nINSERT INTO \"Passwords\" SELECT * FROM \"Passwords_temp\";\nINSERT INTO \"TotpCodes\" SELECT * FROM \"TotpCodes_temp\";\n\n-- =====================================================================================\n-- Date Format Normalization Migration\n-- =====================================================================================\n-- This migration normalizes ALL date fields to the standard format: 'yyyy-MM-dd HH:mm:ss.fff'\n-- Previously the different clients used different date formats which complicate date parsing.\n-- From version 0.24.0 onwards, all new dates are stored in this standard format.\n\n-- Update Aliases table (CreatedAt, UpdatedAt, BirthDate)\nUPDATE \"Aliases\" SET \"CreatedAt\" =\n CASE\n -- Already in correct format (yyyy-MM-dd HH:mm:ss.fff) - no change\n WHEN \"CreatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9] [0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9][0-9][0-9]'\n THEN \"CreatedAt\"\n\n -- ISO 8601 with milliseconds (yyyy-MM-ddTHH:mm:ss.fffZ) -> Replace T with space, remove Z and everything after .fff\n WHEN \"CreatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]T[0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9]*'\n THEN substr(\"CreatedAt\", 1, 10) || ' ' || substr(\"CreatedAt\", 12, 12)\n\n -- Without milliseconds (yyyy-MM-dd HH:mm:ss or yyyy-MM-ddTHH:mm:ssZ) -> Add .000\n WHEN \"CreatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9][T ][0-9][0-9]:[0-9][0-9]:[0-9][0-9]*'\n THEN substr(\"CreatedAt\", 1, 10) || ' ' || substr(replace(\"CreatedAt\", 'T', ' '), 12, 8) || '.000'\n\n -- Fallback: if none match, keep as-is (edge case)\n ELSE \"CreatedAt\"\n END;\n\nUPDATE \"Aliases\" SET \"UpdatedAt\" =\n CASE\n WHEN \"UpdatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9] [0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9][0-9][0-9]'\n THEN \"UpdatedAt\"\n WHEN \"UpdatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]T[0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9]*'\n THEN substr(\"UpdatedAt\", 1, 10) || ' ' || substr(\"UpdatedAt\", 12, 12)\n WHEN \"UpdatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9][T ][0-9][0-9]:[0-9][0-9]:[0-9][0-9]*'\n THEN substr(\"UpdatedAt\", 1, 10) || ' ' || substr(replace(\"UpdatedAt\", 'T', ' '), 12, 8) || '.000'\n ELSE \"UpdatedAt\"\n END;\n\n-- BirthDate: Always set time to 00:00:00 (no milliseconds for birth dates)\nUPDATE \"Aliases\" SET \"BirthDate\" =\n CASE\n -- If empty or already '0001-01-01 00:00:00', keep as-is\n WHEN \"BirthDate\" = '' OR \"BirthDate\" = '0001-01-01 00:00:00'\n THEN \"BirthDate\"\n\n -- If already in correct format (yyyy-MM-dd 00:00:00), keep as-is\n WHEN \"BirthDate\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9] 00:00:00'\n THEN \"BirthDate\"\n\n -- Extract date part and set time to 00:00:00\n WHEN \"BirthDate\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]*'\n THEN substr(\"BirthDate\", 1, 10) || ' 00:00:00'\n\n -- Fallback\n ELSE \"BirthDate\"\n END;\n\n-- Update Services table (CreatedAt, UpdatedAt)\nUPDATE \"Services\" SET \"CreatedAt\" =\n CASE\n WHEN \"CreatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9] [0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9][0-9][0-9]'\n THEN \"CreatedAt\"\n WHEN \"CreatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]T[0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9]*'\n THEN substr(\"CreatedAt\", 1, 10) || ' ' || substr(\"CreatedAt\", 12, 12)\n WHEN \"CreatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9][T ][0-9][0-9]:[0-9][0-9]:[0-9][0-9]*'\n THEN substr(\"CreatedAt\", 1, 10) || ' ' || substr(replace(\"CreatedAt\", 'T', ' '), 12, 8) || '.000'\n ELSE \"CreatedAt\"\n END;\n\nUPDATE \"Services\" SET \"UpdatedAt\" =\n CASE\n WHEN \"UpdatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9] [0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9][0-9][0-9]'\n THEN \"UpdatedAt\"\n WHEN \"UpdatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]T[0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9]*'\n THEN substr(\"UpdatedAt\", 1, 10) || ' ' || substr(\"UpdatedAt\", 12, 12)\n WHEN \"UpdatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9][T ][0-9][0-9]:[0-9][0-9]:[0-9][0-9]*'\n THEN substr(\"UpdatedAt\", 1, 10) || ' ' || substr(replace(\"UpdatedAt\", 'T', ' '), 12, 8) || '.000'\n ELSE \"UpdatedAt\"\n END;\n\n-- Update EncryptionKeys table (CreatedAt, UpdatedAt)\nUPDATE \"EncryptionKeys\" SET \"CreatedAt\" =\n CASE\n WHEN \"CreatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9] [0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9][0-9][0-9]'\n THEN \"CreatedAt\"\n WHEN \"CreatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]T[0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9]*'\n THEN substr(\"CreatedAt\", 1, 10) || ' ' || substr(\"CreatedAt\", 12, 12)\n WHEN \"CreatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9][T ][0-9][0-9]:[0-9][0-9]:[0-9][0-9]*'\n THEN substr(\"CreatedAt\", 1, 10) || ' ' || substr(replace(\"CreatedAt\", 'T', ' '), 12, 8) || '.000'\n ELSE \"CreatedAt\"\n END;\n\nUPDATE \"EncryptionKeys\" SET \"UpdatedAt\" =\n CASE\n WHEN \"UpdatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9] [0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9][0-9][0-9]'\n THEN \"UpdatedAt\"\n WHEN \"UpdatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]T[0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9]*'\n THEN substr(\"UpdatedAt\", 1, 10) || ' ' || substr(\"UpdatedAt\", 12, 12)\n WHEN \"UpdatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9][T ][0-9][0-9]:[0-9][0-9]:[0-9][0-9]*'\n THEN substr(\"UpdatedAt\", 1, 10) || ' ' || substr(replace(\"UpdatedAt\", 'T', ' '), 12, 8) || '.000'\n ELSE \"UpdatedAt\"\n END;\n\n-- Update Settings table (CreatedAt, UpdatedAt)\nUPDATE \"Settings\" SET \"CreatedAt\" =\n CASE\n WHEN \"CreatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9] [0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9][0-9][0-9]'\n THEN \"CreatedAt\"\n WHEN \"CreatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]T[0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9]*'\n THEN substr(\"CreatedAt\", 1, 10) || ' ' || substr(\"CreatedAt\", 12, 12)\n WHEN \"CreatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9][T ][0-9][0-9]:[0-9][0-9]:[0-9][0-9]*'\n THEN substr(\"CreatedAt\", 1, 10) || ' ' || substr(replace(\"CreatedAt\", 'T', ' '), 12, 8) || '.000'\n ELSE \"CreatedAt\"\n END;\n\nUPDATE \"Settings\" SET \"UpdatedAt\" =\n CASE\n WHEN \"UpdatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9] [0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9][0-9][0-9]'\n THEN \"UpdatedAt\"\n WHEN \"UpdatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]T[0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9]*'\n THEN substr(\"UpdatedAt\", 1, 10) || ' ' || substr(\"UpdatedAt\", 12, 12)\n WHEN \"UpdatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9][T ][0-9][0-9]:[0-9][0-9]:[0-9][0-9]*'\n THEN substr(\"UpdatedAt\", 1, 10) || ' ' || substr(replace(\"UpdatedAt\", 'T', ' '), 12, 8) || '.000'\n ELSE \"UpdatedAt\"\n END;\n\n-- Update Credentials table (CreatedAt, UpdatedAt)\nUPDATE \"Credentials\" SET \"CreatedAt\" =\n CASE\n WHEN \"CreatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9] [0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9][0-9][0-9]'\n THEN \"CreatedAt\"\n WHEN \"CreatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]T[0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9]*'\n THEN substr(\"CreatedAt\", 1, 10) || ' ' || substr(\"CreatedAt\", 12, 12)\n WHEN \"CreatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9][T ][0-9][0-9]:[0-9][0-9]:[0-9][0-9]*'\n THEN substr(\"CreatedAt\", 1, 10) || ' ' || substr(replace(\"CreatedAt\", 'T', ' '), 12, 8) || '.000'\n ELSE \"CreatedAt\"\n END;\n\nUPDATE \"Credentials\" SET \"UpdatedAt\" =\n CASE\n WHEN \"UpdatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9] [0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9][0-9][0-9]'\n THEN \"UpdatedAt\"\n WHEN \"UpdatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]T[0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9]*'\n THEN substr(\"UpdatedAt\", 1, 10) || ' ' || substr(\"UpdatedAt\", 12, 12)\n WHEN \"UpdatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9][T ][0-9][0-9]:[0-9][0-9]:[0-9][0-9]*'\n THEN substr(\"UpdatedAt\", 1, 10) || ' ' || substr(replace(\"UpdatedAt\", 'T', ' '), 12, 8) || '.000'\n ELSE \"UpdatedAt\"\n END;\n\n-- Update Attachments table (CreatedAt, UpdatedAt)\nUPDATE \"Attachments\" SET \"CreatedAt\" =\n CASE\n WHEN \"CreatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9] [0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9][0-9][0-9]'\n THEN \"CreatedAt\"\n WHEN \"CreatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]T[0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9]*'\n THEN substr(\"CreatedAt\", 1, 10) || ' ' || substr(\"CreatedAt\", 12, 12)\n WHEN \"CreatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9][T ][0-9][0-9]:[0-9][0-9]:[0-9][0-9]*'\n THEN substr(\"CreatedAt\", 1, 10) || ' ' || substr(replace(\"CreatedAt\", 'T', ' '), 12, 8) || '.000'\n ELSE \"CreatedAt\"\n END;\n\nUPDATE \"Attachments\" SET \"UpdatedAt\" =\n CASE\n WHEN \"UpdatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9] [0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9][0-9][0-9]'\n THEN \"UpdatedAt\"\n WHEN \"UpdatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]T[0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9]*'\n THEN substr(\"UpdatedAt\", 1, 10) || ' ' || substr(\"UpdatedAt\", 12, 12)\n WHEN \"UpdatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9][T ][0-9][0-9]:[0-9][0-9]:[0-9][0-9]*'\n THEN substr(\"UpdatedAt\", 1, 10) || ' ' || substr(replace(\"UpdatedAt\", 'T', ' '), 12, 8) || '.000'\n ELSE \"UpdatedAt\"\n END;\n\n-- Update Passwords table (CreatedAt, UpdatedAt)\nUPDATE \"Passwords\" SET \"CreatedAt\" =\n CASE\n WHEN \"CreatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9] [0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9][0-9][0-9]'\n THEN \"CreatedAt\"\n WHEN \"CreatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]T[0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9]*'\n THEN substr(\"CreatedAt\", 1, 10) || ' ' || substr(\"CreatedAt\", 12, 12)\n WHEN \"CreatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9][T ][0-9][0-9]:[0-9][0-9]:[0-9][0-9]*'\n THEN substr(\"CreatedAt\", 1, 10) || ' ' || substr(replace(\"CreatedAt\", 'T', ' '), 12, 8) || '.000'\n ELSE \"CreatedAt\"\n END;\n\nUPDATE \"Passwords\" SET \"UpdatedAt\" =\n CASE\n WHEN \"UpdatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9] [0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9][0-9][0-9]'\n THEN \"UpdatedAt\"\n WHEN \"UpdatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]T[0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9]*'\n THEN substr(\"UpdatedAt\", 1, 10) || ' ' || substr(\"UpdatedAt\", 12, 12)\n WHEN \"UpdatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9][T ][0-9][0-9]:[0-9][0-9]:[0-9][0-9]*'\n THEN substr(\"UpdatedAt\", 1, 10) || ' ' || substr(replace(\"UpdatedAt\", 'T', ' '), 12, 8) || '.000'\n ELSE \"UpdatedAt\"\n END;\n\n-- Update TotpCodes table (CreatedAt, UpdatedAt)\nUPDATE \"TotpCodes\" SET \"CreatedAt\" =\n CASE\n WHEN \"CreatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9] [0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9][0-9][0-9]'\n THEN \"CreatedAt\"\n WHEN \"CreatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]T[0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9]*'\n THEN substr(\"CreatedAt\", 1, 10) || ' ' || substr(\"CreatedAt\", 12, 12)\n WHEN \"CreatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9][T ][0-9][0-9]:[0-9][0-9]:[0-9][0-9]*'\n THEN substr(\"CreatedAt\", 1, 10) || ' ' || substr(replace(\"CreatedAt\", 'T', ' '), 12, 8) || '.000'\n ELSE \"CreatedAt\"\n END;\n\nUPDATE \"TotpCodes\" SET \"UpdatedAt\" =\n CASE\n WHEN \"UpdatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9] [0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9][0-9][0-9]'\n THEN \"UpdatedAt\"\n WHEN \"UpdatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]T[0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9]*'\n THEN substr(\"UpdatedAt\", 1, 10) || ' ' || substr(\"UpdatedAt\", 12, 12)\n WHEN \"UpdatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9][T ][0-9][0-9]:[0-9][0-9]:[0-9][0-9]*'\n THEN substr(\"UpdatedAt\", 1, 10) || ' ' || substr(replace(\"UpdatedAt\", 'T', ' '), 12, 8) || '.000'\n ELSE \"UpdatedAt\"\n END;\n\n-- =====================================================================================\n-- End of Date Format Normalization Migration\n-- =====================================================================================\n\n-- Recreate indexes\nCREATE INDEX \"IX_Credentials_AliasId\" ON \"Credentials\" (\"AliasId\");\nCREATE INDEX \"IX_Credentials_ServiceId\" ON \"Credentials\" (\"ServiceId\");\nCREATE INDEX \"IX_Attachments_CredentialId\" ON \"Attachments\" (\"CredentialId\");\nCREATE INDEX \"IX_Passwords_CredentialId\" ON \"Passwords\" (\"CredentialId\");\nCREATE INDEX \"IX_TotpCodes_CredentialId\" ON \"TotpCodes\" (\"CredentialId\");\n\n-- Clean up temp tables\nDROP TABLE \"__EFMigrationsHistory_temp\";\nDROP TABLE \"Aliases_temp\";\nDROP TABLE \"Services_temp\";\nDROP TABLE \"EncryptionKeys_temp\";\nDROP TABLE \"Settings_temp\";\nDROP TABLE \"Credentials_temp\";\nDROP TABLE \"Attachments_temp\";\nDROP TABLE \"Passwords_temp\";\nDROP TABLE \"TotpCodes_temp\";\n\nPRAGMA foreign_keys = ON;\n\n\nCREATE TABLE \"Passkeys\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_Passkeys\" PRIMARY KEY,\n \"RpId\" TEXT COLLATE NOCASE NOT NULL,\n \"UserHandle\" BLOB NOT NULL,\n \"PublicKey\" TEXT NOT NULL,\n \"PrivateKey\" TEXT NOT NULL,\n \"PrfKey\" BLOB NULL,\n \"DisplayName\" TEXT NOT NULL,\n \"AdditionalData\" BLOB NULL,\n \"CredentialId\" TEXT NOT NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"UpdatedAt\" TEXT NOT NULL,\n \"IsDeleted\" INTEGER NOT NULL,\n CONSTRAINT \"FK_Passkeys_Credentials_CredentialId\" FOREIGN KEY (\"CredentialId\") REFERENCES \"Credentials\" (\"Id\") ON DELETE CASCADE\n);\n\nCREATE INDEX \"IX_Passkeys_CredentialId\" ON \"Passkeys\" (\"CredentialId\");\n\nCREATE INDEX \"IX_Passkeys_RpId\" ON \"Passkeys\" (\"RpId\");\n\nINSERT INTO \"__EFMigrationsHistory\" (\"MigrationId\", \"ProductVersion\")\nVALUES ('20251014122838_1.6.0-AddPasskeys', '9.0.4');\n\nALTER TABLE \"TotpCodes\" RENAME COLUMN \"CredentialId\" TO \"ItemId\";\n\nDROP INDEX IF EXISTS \"IX_TotpCodes_CredentialId\";\n\nCREATE INDEX IF NOT EXISTS \"IX_TotpCodes_ItemId\" ON \"TotpCodes\" (\"ItemId\");\n\nALTER TABLE \"Passkeys\" RENAME COLUMN \"CredentialId\" TO \"ItemId\";\n\nDROP INDEX IF EXISTS \"IX_Passkeys_CredentialId\";\n\nCREATE INDEX IF NOT EXISTS \"IX_Passkeys_ItemId\" ON \"Passkeys\" (\"ItemId\");\n\nALTER TABLE \"Attachments\" RENAME COLUMN \"CredentialId\" TO \"ItemId\";\n\nDROP INDEX IF EXISTS \"IX_Attachments_CredentialId\";\n\nCREATE INDEX IF NOT EXISTS \"IX_Attachments_ItemId\" ON \"Attachments\" (\"ItemId\");\n\nCREATE TABLE \"FieldDefinitions\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_FieldDefinitions\" PRIMARY KEY,\n \"FieldType\" TEXT NOT NULL,\n \"Label\" TEXT NOT NULL,\n \"IsMultiValue\" INTEGER NOT NULL,\n \"IsHidden\" INTEGER NOT NULL,\n \"EnableHistory\" INTEGER NOT NULL,\n \"Weight\" INTEGER NOT NULL,\n \"ApplicableToTypes\" TEXT NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"UpdatedAt\" TEXT NOT NULL,\n \"IsDeleted\" INTEGER NOT NULL\n);\n\nCREATE TABLE \"Folders\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_Folders\" PRIMARY KEY,\n \"Name\" TEXT NOT NULL,\n \"ParentFolderId\" TEXT NULL,\n \"Weight\" INTEGER NOT NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"UpdatedAt\" TEXT NOT NULL,\n \"IsDeleted\" INTEGER NOT NULL,\n CONSTRAINT \"FK_Folders_Folders_ParentFolderId\" FOREIGN KEY (\"ParentFolderId\") REFERENCES \"Folders\" (\"Id\") ON DELETE CASCADE\n);\n\nCREATE TABLE \"Logos\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_Logos\" PRIMARY KEY,\n \"Source\" TEXT NOT NULL,\n \"FileData\" BLOB NULL,\n \"MimeType\" TEXT NULL,\n \"FetchedAt\" TEXT NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"UpdatedAt\" TEXT NOT NULL,\n \"IsDeleted\" INTEGER NOT NULL\n);\n\nCREATE TABLE \"Tags\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_Tags\" PRIMARY KEY,\n \"Name\" TEXT NOT NULL,\n \"Color\" TEXT NULL,\n \"DisplayOrder\" INTEGER NOT NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"UpdatedAt\" TEXT NOT NULL,\n \"IsDeleted\" INTEGER NOT NULL\n);\n\nCREATE TABLE \"Items\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_Items\" PRIMARY KEY,\n \"Name\" TEXT NULL,\n \"ItemType\" TEXT NOT NULL,\n \"LogoId\" TEXT NULL,\n \"DeletedAt\" TEXT NULL,\n \"FolderId\" TEXT NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"UpdatedAt\" TEXT NOT NULL,\n \"IsDeleted\" INTEGER NOT NULL,\n CONSTRAINT \"FK_Items_Folders_FolderId\" FOREIGN KEY (\"FolderId\") REFERENCES \"Folders\" (\"Id\") ON DELETE SET NULL,\n CONSTRAINT \"FK_Items_Logos_LogoId\" FOREIGN KEY (\"LogoId\") REFERENCES \"Logos\" (\"Id\") ON DELETE SET NULL\n);\n\nCREATE TABLE \"FieldHistories\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_FieldHistories\" PRIMARY KEY,\n \"ItemId\" TEXT NOT NULL,\n \"FieldDefinitionId\" TEXT NULL,\n \"FieldKey\" TEXT NULL,\n \"ValueSnapshot\" TEXT NOT NULL,\n \"ChangedAt\" TEXT NOT NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"UpdatedAt\" TEXT NOT NULL,\n \"IsDeleted\" INTEGER NOT NULL,\n CONSTRAINT \"FK_FieldHistories_FieldDefinitions_FieldDefinitionId\" FOREIGN KEY (\"FieldDefinitionId\") REFERENCES \"FieldDefinitions\" (\"Id\") ON DELETE CASCADE,\n CONSTRAINT \"FK_FieldHistories_Items_ItemId\" FOREIGN KEY (\"ItemId\") REFERENCES \"Items\" (\"Id\") ON DELETE CASCADE\n);\n\nCREATE TABLE \"FieldValues\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_FieldValues\" PRIMARY KEY,\n \"ItemId\" TEXT NOT NULL,\n \"FieldDefinitionId\" TEXT NULL,\n \"FieldKey\" TEXT NULL,\n \"Value\" TEXT NULL,\n \"Weight\" INTEGER NOT NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"UpdatedAt\" TEXT NOT NULL,\n \"IsDeleted\" INTEGER NOT NULL,\n CONSTRAINT \"FK_FieldValues_FieldDefinitions_FieldDefinitionId\" FOREIGN KEY (\"FieldDefinitionId\") REFERENCES \"FieldDefinitions\" (\"Id\") ON DELETE CASCADE,\n CONSTRAINT \"FK_FieldValues_Items_ItemId\" FOREIGN KEY (\"ItemId\") REFERENCES \"Items\" (\"Id\") ON DELETE CASCADE\n);\n\nCREATE TABLE \"ItemTags\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_ItemTags\" PRIMARY KEY,\n \"ItemId\" TEXT NOT NULL,\n \"TagId\" TEXT NOT NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"UpdatedAt\" TEXT NOT NULL,\n \"IsDeleted\" INTEGER NOT NULL,\n CONSTRAINT \"FK_ItemTags_Items_ItemId\" FOREIGN KEY (\"ItemId\") REFERENCES \"Items\" (\"Id\") ON DELETE CASCADE,\n CONSTRAINT \"FK_ItemTags_Tags_TagId\" FOREIGN KEY (\"TagId\") REFERENCES \"Tags\" (\"Id\") ON DELETE CASCADE\n);\n\nCREATE INDEX \"IX_FieldHistories_FieldDefinitionId\" ON \"FieldHistories\" (\"FieldDefinitionId\");\n\nCREATE INDEX \"IX_FieldHistories_ItemId\" ON \"FieldHistories\" (\"ItemId\");\n\nCREATE INDEX \"IX_FieldValues_FieldDefinitionId\" ON \"FieldValues\" (\"FieldDefinitionId\");\n\nCREATE INDEX \"IX_FieldValues_FieldKey\" ON \"FieldValues\" (\"FieldKey\");\n\nCREATE INDEX \"IX_FieldValues_ItemId\" ON \"FieldValues\" (\"ItemId\");\n\nCREATE INDEX \"IX_FieldValues_ItemId_FieldDefinitionId_Weight\" ON \"FieldValues\" (\"ItemId\", \"FieldDefinitionId\", \"Weight\");\n\nCREATE INDEX \"IX_FieldValues_ItemId_FieldKey\" ON \"FieldValues\" (\"ItemId\", \"FieldKey\");\n\nCREATE INDEX \"IX_Folders_ParentFolderId\" ON \"Folders\" (\"ParentFolderId\");\n\nCREATE INDEX \"IX_Items_FolderId\" ON \"Items\" (\"FolderId\");\n\nCREATE INDEX \"IX_Items_LogoId\" ON \"Items\" (\"LogoId\");\n\nCREATE INDEX \"IX_ItemTags_ItemId\" ON \"ItemTags\" (\"ItemId\");\n\nCREATE UNIQUE INDEX \"IX_ItemTags_ItemId_TagId\" ON \"ItemTags\" (\"ItemId\", \"TagId\");\n\nCREATE INDEX \"IX_ItemTags_TagId\" ON \"ItemTags\" (\"TagId\");\n\nCREATE UNIQUE INDEX \"IX_Logos_Source\" ON \"Logos\" (\"Source\");\n\nCREATE INDEX \"IX_Tags_Name\" ON \"Tags\" (\"Name\");\n\n\n INSERT INTO Items (Id, Name, ItemType, LogoId, FolderId, CreatedAt, UpdatedAt, IsDeleted)\n SELECT\n c.Id,\n s.Name AS Name,\n CASE\n WHEN a.Id IS NOT NULL AND (\n (a.FirstName IS NOT NULL AND a.FirstName != '') OR\n (a.LastName IS NOT NULL AND a.LastName != '') OR\n (a.Gender IS NOT NULL AND a.Gender != '') OR\n (a.BirthDate IS NOT NULL AND a.BirthDate != '' AND a.BirthDate NOT LIKE '0001-%')\n ) THEN 'Alias'\n ELSE 'Login'\n END AS ItemType,\n NULL AS LogoId,\n NULL AS FolderId,\n c.CreatedAt,\n c.UpdatedAt,\n c.IsDeleted\n FROM Credentials c\n LEFT JOIN Services s ON s.Id = c.ServiceId\n LEFT JOIN Aliases a ON a.Id = c.AliasId;\n \n\n\n INSERT INTO Logos (Id, Source, FileData, MimeType, FetchedAt, CreatedAt, UpdatedAt, IsDeleted)\n SELECT\n UPPER(SUBSTR(hex(randomblob(4)), 1, 8) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(6)), 1, 12)) AS Id,\n -- Extract and normalize hostname: remove protocol, path, lowercase, and www. prefix\n REPLACE(\n LOWER(\n SUBSTR(\n CASE\n WHEN s.Url LIKE 'https://%' THEN SUBSTR(s.Url, 9)\n WHEN s.Url LIKE 'http://%' THEN SUBSTR(s.Url, 8)\n ELSE s.Url\n END,\n 1,\n CASE\n WHEN INSTR(\n CASE\n WHEN s.Url LIKE 'https://%' THEN SUBSTR(s.Url, 9)\n WHEN s.Url LIKE 'http://%' THEN SUBSTR(s.Url, 8)\n ELSE s.Url\n END, '/') > 0\n THEN INSTR(\n CASE\n WHEN s.Url LIKE 'https://%' THEN SUBSTR(s.Url, 9)\n WHEN s.Url LIKE 'http://%' THEN SUBSTR(s.Url, 8)\n ELSE s.Url\n END, '/') - 1\n ELSE LENGTH(\n CASE\n WHEN s.Url LIKE 'https://%' THEN SUBSTR(s.Url, 9)\n WHEN s.Url LIKE 'http://%' THEN SUBSTR(s.Url, 8)\n ELSE s.Url\n END)\n END\n )\n ),\n 'www.', ''\n ) AS Source,\n s.Logo AS FileData,\n 'image/png' AS MimeType,\n NULL AS FetchedAt,\n MIN(s.CreatedAt) AS CreatedAt,\n MAX(s.UpdatedAt) AS UpdatedAt,\n 0 AS IsDeleted\n FROM Services s\n WHERE s.Logo IS NOT NULL AND s.Url IS NOT NULL AND s.Url != ''\n GROUP BY REPLACE(\n LOWER(\n SUBSTR(\n CASE\n WHEN s.Url LIKE 'https://%' THEN SUBSTR(s.Url, 9)\n WHEN s.Url LIKE 'http://%' THEN SUBSTR(s.Url, 8)\n ELSE s.Url\n END,\n 1,\n CASE\n WHEN INSTR(\n CASE\n WHEN s.Url LIKE 'https://%' THEN SUBSTR(s.Url, 9)\n WHEN s.Url LIKE 'http://%' THEN SUBSTR(s.Url, 8)\n ELSE s.Url\n END, '/') > 0\n THEN INSTR(\n CASE\n WHEN s.Url LIKE 'https://%' THEN SUBSTR(s.Url, 9)\n WHEN s.Url LIKE 'http://%' THEN SUBSTR(s.Url, 8)\n ELSE s.Url\n END, '/') - 1\n ELSE LENGTH(\n CASE\n WHEN s.Url LIKE 'https://%' THEN SUBSTR(s.Url, 9)\n WHEN s.Url LIKE 'http://%' THEN SUBSTR(s.Url, 8)\n ELSE s.Url\n END)\n END\n )\n ),\n 'www.', ''\n );\n \n\n\n UPDATE Items\n SET LogoId = (\n SELECT l.Id FROM Logos l\n INNER JOIN Services s ON REPLACE(\n LOWER(\n SUBSTR(\n CASE\n WHEN s.Url LIKE 'https://%' THEN SUBSTR(s.Url, 9)\n WHEN s.Url LIKE 'http://%' THEN SUBSTR(s.Url, 8)\n ELSE s.Url\n END,\n 1,\n CASE\n WHEN INSTR(\n CASE\n WHEN s.Url LIKE 'https://%' THEN SUBSTR(s.Url, 9)\n WHEN s.Url LIKE 'http://%' THEN SUBSTR(s.Url, 8)\n ELSE s.Url\n END, '/') > 0\n THEN INSTR(\n CASE\n WHEN s.Url LIKE 'https://%' THEN SUBSTR(s.Url, 9)\n WHEN s.Url LIKE 'http://%' THEN SUBSTR(s.Url, 8)\n ELSE s.Url\n END, '/') - 1\n ELSE LENGTH(\n CASE\n WHEN s.Url LIKE 'https://%' THEN SUBSTR(s.Url, 9)\n WHEN s.Url LIKE 'http://%' THEN SUBSTR(s.Url, 8)\n ELSE s.Url\n END)\n END\n )\n ),\n 'www.', ''\n ) = l.Source\n INNER JOIN Credentials c ON c.ServiceId = s.Id\n WHERE c.Id = Items.Id\n LIMIT 1\n )\n WHERE EXISTS (\n SELECT 1 FROM Credentials c\n INNER JOIN Services s ON s.Id = c.ServiceId\n WHERE c.Id = Items.Id AND s.Logo IS NOT NULL\n );\n \n\n\n INSERT INTO FieldValues (Id, ItemId, FieldDefinitionId, FieldKey, Value, Weight, CreatedAt, UpdatedAt, IsDeleted)\n SELECT\n UPPER(SUBSTR(hex(randomblob(4)), 1, 8) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(6)), 1, 12)) AS Id,\n c.Id AS ItemId,\n NULL AS FieldDefinitionId,\n 'login.url' AS FieldKey,\n s.Url AS Value,\n 0 AS Weight,\n s.UpdatedAt AS CreatedAt,\n s.UpdatedAt AS UpdatedAt,\n 0 AS IsDeleted\n FROM Credentials c\n INNER JOIN Services s ON s.Id = c.ServiceId\n WHERE s.Url IS NOT NULL AND s.Url != '';\n \n\n\n INSERT INTO FieldValues (Id, ItemId, FieldDefinitionId, FieldKey, Value, Weight, CreatedAt, UpdatedAt, IsDeleted)\n SELECT\n UPPER(SUBSTR(hex(randomblob(4)), 1, 8) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(6)), 1, 12)) AS Id,\n c.Id AS ItemId,\n NULL AS FieldDefinitionId,\n 'login.username' AS FieldKey,\n c.Username AS Value,\n 0 AS Weight,\n c.UpdatedAt AS CreatedAt,\n c.UpdatedAt AS UpdatedAt,\n 0 AS IsDeleted\n FROM Credentials c\n WHERE c.Username IS NOT NULL AND c.Username != '';\n \n\n\n INSERT INTO FieldValues (Id, ItemId, FieldDefinitionId, FieldKey, Value, Weight, CreatedAt, UpdatedAt, IsDeleted)\n SELECT\n UPPER(SUBSTR(hex(randomblob(4)), 1, 8) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(6)), 1, 12)) AS Id,\n c.Id AS ItemId,\n NULL AS FieldDefinitionId,\n 'login.notes' AS FieldKey,\n c.Notes AS Value,\n 0 AS Weight,\n c.UpdatedAt AS CreatedAt,\n c.UpdatedAt AS UpdatedAt,\n 0 AS IsDeleted\n FROM Credentials c\n WHERE c.Notes IS NOT NULL AND c.Notes != '';\n \n\n\n INSERT INTO FieldValues (Id, ItemId, FieldDefinitionId, FieldKey, Value, Weight, CreatedAt, UpdatedAt, IsDeleted)\n SELECT\n UPPER(SUBSTR(hex(randomblob(4)), 1, 8) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(6)), 1, 12)) AS Id,\n p.CredentialId AS ItemId,\n NULL AS FieldDefinitionId,\n 'login.password' AS FieldKey,\n p.Value AS Value,\n 0 AS Weight,\n p.UpdatedAt AS CreatedAt,\n p.UpdatedAt AS UpdatedAt,\n 0 AS IsDeleted\n FROM Passwords p\n INNER JOIN (\n SELECT CredentialId, MAX(UpdatedAt) AS MaxUpdated, MAX(Id) AS MaxId\n FROM Passwords\n WHERE IsDeleted = 0\n GROUP BY CredentialId\n ) pm ON p.CredentialId = pm.CredentialId AND p.UpdatedAt = pm.MaxUpdated AND p.Id = pm.MaxId\n WHERE p.IsDeleted = 0;\n \n\n\n INSERT INTO FieldValues (Id, ItemId, FieldDefinitionId, FieldKey, Value, Weight, CreatedAt, UpdatedAt, IsDeleted)\n SELECT\n UPPER(SUBSTR(hex(randomblob(4)), 1, 8) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(6)), 1, 12)) AS Id,\n c.Id AS ItemId,\n NULL AS FieldDefinitionId,\n 'login.email' AS FieldKey,\n a.Email AS Value,\n 0 AS Weight,\n a.UpdatedAt AS CreatedAt,\n a.UpdatedAt AS UpdatedAt,\n 0 AS IsDeleted\n FROM Credentials c\n INNER JOIN Aliases a ON a.Id = c.AliasId\n WHERE a.Email IS NOT NULL AND a.Email != '';\n \n\n\n INSERT INTO FieldValues (Id, ItemId, FieldDefinitionId, FieldKey, Value, Weight, CreatedAt, UpdatedAt, IsDeleted)\n SELECT\n UPPER(SUBSTR(hex(randomblob(4)), 1, 8) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(6)), 1, 12)) AS Id,\n c.Id AS ItemId,\n NULL AS FieldDefinitionId,\n 'alias.first_name' AS FieldKey,\n a.FirstName AS Value,\n 0 AS Weight,\n a.UpdatedAt AS CreatedAt,\n a.UpdatedAt AS UpdatedAt,\n 0 AS IsDeleted\n FROM Credentials c\n INNER JOIN Aliases a ON a.Id = c.AliasId\n WHERE a.FirstName IS NOT NULL AND a.FirstName != '';\n \n\n\n INSERT INTO FieldValues (Id, ItemId, FieldDefinitionId, FieldKey, Value, Weight, CreatedAt, UpdatedAt, IsDeleted)\n SELECT\n UPPER(SUBSTR(hex(randomblob(4)), 1, 8) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(6)), 1, 12)) AS Id,\n c.Id AS ItemId,\n NULL AS FieldDefinitionId,\n 'alias.last_name' AS FieldKey,\n a.LastName AS Value,\n 0 AS Weight,\n a.UpdatedAt AS CreatedAt,\n a.UpdatedAt AS UpdatedAt,\n 0 AS IsDeleted\n FROM Credentials c\n INNER JOIN Aliases a ON a.Id = c.AliasId\n WHERE a.LastName IS NOT NULL AND a.LastName != '';\n \n\n\n INSERT INTO FieldValues (Id, ItemId, FieldDefinitionId, FieldKey, Value, Weight, CreatedAt, UpdatedAt, IsDeleted)\n SELECT\n UPPER(SUBSTR(hex(randomblob(4)), 1, 8) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(6)), 1, 12)) AS Id,\n c.Id AS ItemId,\n NULL AS FieldDefinitionId,\n 'alias.gender' AS FieldKey,\n a.Gender AS Value,\n 0 AS Weight,\n a.UpdatedAt AS CreatedAt,\n a.UpdatedAt AS UpdatedAt,\n 0 AS IsDeleted\n FROM Credentials c\n INNER JOIN Aliases a ON a.Id = c.AliasId\n WHERE a.Gender IS NOT NULL AND a.Gender != '';\n \n\n\n INSERT INTO FieldValues (Id, ItemId, FieldDefinitionId, FieldKey, Value, Weight, CreatedAt, UpdatedAt, IsDeleted)\n SELECT\n UPPER(SUBSTR(hex(randomblob(4)), 1, 8) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(6)), 1, 12)) AS Id,\n c.Id AS ItemId,\n NULL AS FieldDefinitionId,\n 'alias.birthdate' AS FieldKey,\n SUBSTR(a.BirthDate, 1, 10) AS Value,\n 0 AS Weight,\n a.UpdatedAt AS CreatedAt,\n a.UpdatedAt AS UpdatedAt,\n 0 AS IsDeleted\n FROM Credentials c\n INNER JOIN Aliases a ON a.Id = c.AliasId\n WHERE a.BirthDate IS NOT NULL AND a.BirthDate != '' AND a.BirthDate NOT LIKE '0001-%';\n \n\nDROP TABLE \"Passwords\";\n\nDROP TABLE \"Credentials\";\n\nDROP TABLE \"Aliases\";\n\nDROP TABLE \"Services\";\n\nCREATE TABLE \"ef_temp_Attachments\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_Attachments\" PRIMARY KEY,\n \"Blob\" BLOB NOT NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"Filename\" TEXT NOT NULL,\n \"IsDeleted\" INTEGER NOT NULL,\n \"ItemId\" TEXT NOT NULL,\n \"UpdatedAt\" TEXT NOT NULL,\n CONSTRAINT \"FK_Attachments_Items_ItemId\" FOREIGN KEY (\"ItemId\") REFERENCES \"Items\" (\"Id\") ON DELETE CASCADE\n);\n\nINSERT INTO \"ef_temp_Attachments\" (\"Id\", \"Blob\", \"CreatedAt\", \"Filename\", \"IsDeleted\", \"ItemId\", \"UpdatedAt\")\nSELECT \"Id\", \"Blob\", \"CreatedAt\", \"Filename\", \"IsDeleted\", \"ItemId\", \"UpdatedAt\"\nFROM \"Attachments\";\n\nCREATE TABLE \"ef_temp_Passkeys\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_Passkeys\" PRIMARY KEY,\n \"AdditionalData\" BLOB NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"DisplayName\" TEXT NOT NULL,\n \"IsDeleted\" INTEGER NOT NULL,\n \"ItemId\" TEXT NOT NULL,\n \"PrfKey\" BLOB NULL,\n \"PrivateKey\" TEXT NOT NULL,\n \"PublicKey\" TEXT NOT NULL,\n \"RpId\" TEXT COLLATE NOCASE NOT NULL,\n \"UpdatedAt\" TEXT NOT NULL,\n \"UserHandle\" BLOB NOT NULL,\n CONSTRAINT \"FK_Passkeys_Items_ItemId\" FOREIGN KEY (\"ItemId\") REFERENCES \"Items\" (\"Id\") ON DELETE CASCADE\n);\n\nINSERT INTO \"ef_temp_Passkeys\" (\"Id\", \"AdditionalData\", \"CreatedAt\", \"DisplayName\", \"IsDeleted\", \"ItemId\", \"PrfKey\", \"PrivateKey\", \"PublicKey\", \"RpId\", \"UpdatedAt\", \"UserHandle\")\nSELECT \"Id\", \"AdditionalData\", \"CreatedAt\", \"DisplayName\", \"IsDeleted\", \"ItemId\", \"PrfKey\", \"PrivateKey\", \"PublicKey\", \"RpId\", \"UpdatedAt\", \"UserHandle\"\nFROM \"Passkeys\";\n\nCREATE TABLE \"ef_temp_TotpCodes\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_TotpCodes\" PRIMARY KEY,\n \"CreatedAt\" TEXT NOT NULL,\n \"IsDeleted\" INTEGER NOT NULL,\n \"ItemId\" TEXT NOT NULL,\n \"Name\" TEXT NOT NULL,\n \"SecretKey\" TEXT NOT NULL,\n \"UpdatedAt\" TEXT NOT NULL,\n CONSTRAINT \"FK_TotpCodes_Items_ItemId\" FOREIGN KEY (\"ItemId\") REFERENCES \"Items\" (\"Id\") ON DELETE CASCADE\n);\n\nINSERT INTO \"ef_temp_TotpCodes\" (\"Id\", \"CreatedAt\", \"IsDeleted\", \"ItemId\", \"Name\", \"SecretKey\", \"UpdatedAt\")\nSELECT \"Id\", \"CreatedAt\", \"IsDeleted\", \"ItemId\", \"Name\", \"SecretKey\", \"UpdatedAt\"\nFROM \"TotpCodes\";\n\nCOMMIT;\n\nPRAGMA foreign_keys = 0;\n\nBEGIN TRANSACTION;\nDROP TABLE \"Attachments\";\n\nALTER TABLE \"ef_temp_Attachments\" RENAME TO \"Attachments\";\n\nDROP TABLE \"Passkeys\";\n\nALTER TABLE \"ef_temp_Passkeys\" RENAME TO \"Passkeys\";\n\nDROP TABLE \"TotpCodes\";\n\nALTER TABLE \"ef_temp_TotpCodes\" RENAME TO \"TotpCodes\";\n\nCOMMIT;\n\nPRAGMA foreign_keys = 1;\n\nBEGIN TRANSACTION;\nCREATE INDEX \"IX_Attachments_ItemId\" ON \"Attachments\" (\"ItemId\");\n\nCREATE INDEX \"IX_Passkeys_ItemId\" ON \"Passkeys\" (\"ItemId\");\n\nCREATE INDEX \"IX_Passkeys_RpId\" ON \"Passkeys\" (\"RpId\");\n\nCREATE INDEX \"IX_TotpCodes_ItemId\" ON \"TotpCodes\" (\"ItemId\");\n\nCOMMIT;\n\nINSERT INTO \"__EFMigrationsHistory\" (\"MigrationId\", \"ProductVersion\")\nVALUES ('20251213111207_1.7.0-FieldBasedDataModelUpdate', '9.0.4');\n\nBEGIN TRANSACTION;\nINSERT INTO \"__EFMigrationsHistory\" (\"MigrationId\", \"ProductVersion\")\nVALUES ('20260130221620_2.0.0-MajorVersionBump', '9.0.4');\n\nCOMMIT;\n"; /** * Individual migration SQL scripts * Auto-generated from EF Core migrations diff --git a/apps/mobile-app/utils/dist/core/vault/index.js b/apps/mobile-app/utils/dist/core/vault/index.js index e0802c5be..b8ea571cb 100644 --- a/apps/mobile-app/utils/dist/core/vault/index.js +++ b/apps/mobile-app/utils/dist/core/vault/index.js @@ -1296,6 +1296,12 @@ COMMIT; INSERT INTO "__EFMigrationsHistory" ("MigrationId", "ProductVersion") VALUES ('20251213111207_1.7.0-FieldBasedDataModelUpdate', '9.0.4'); + +BEGIN TRANSACTION; +INSERT INTO "__EFMigrationsHistory" ("MigrationId", "ProductVersion") +VALUES ('20260130221620_2.0.0-MajorVersionBump', '9.0.4'); + +COMMIT; `; var MIGRATION_SCRIPTS = { 1: `\uFEFFBEGIN TRANSACTION; @@ -2492,7 +2498,12 @@ CREATE INDEX "IX_TotpCodes_ItemId" ON "TotpCodes" ("ItemId"); COMMIT; INSERT INTO "__EFMigrationsHistory" ("MigrationId", "ProductVersion") -VALUES ('20251213111207_1.7.0-FieldBasedDataModelUpdate', '9.0.4');` +VALUES ('20251213111207_1.7.0-FieldBasedDataModelUpdate', '9.0.4');`, + 12: `\uFEFFBEGIN TRANSACTION; +INSERT INTO "__EFMigrationsHistory" ("MigrationId", "ProductVersion") +VALUES ('20260130221620_2.0.0-MajorVersionBump', '9.0.4'); + +COMMIT;` }; // src/sql/VaultVersions.ts @@ -2579,7 +2590,14 @@ var VAULT_VERSIONS = [ version: "1.7.0", description: "Update to Field-Based Data Model", releaseVersion: "0.26.0", - compatibleUpToVersion: "0.26.0" + compatibleUpToVersion: "0.25.0" + }, + { + revision: 13, + version: "2.0.0", + description: "Update to Field-Based Data Model", + releaseVersion: "0.26.1", + compatibleUpToVersion: "0.25.0" } ]; diff --git a/apps/mobile-app/utils/dist/core/vault/index.mjs b/apps/mobile-app/utils/dist/core/vault/index.mjs index 8c4d5fa37..d5e02f646 100644 --- a/apps/mobile-app/utils/dist/core/vault/index.mjs +++ b/apps/mobile-app/utils/dist/core/vault/index.mjs @@ -1264,6 +1264,12 @@ COMMIT; INSERT INTO "__EFMigrationsHistory" ("MigrationId", "ProductVersion") VALUES ('20251213111207_1.7.0-FieldBasedDataModelUpdate', '9.0.4'); + +BEGIN TRANSACTION; +INSERT INTO "__EFMigrationsHistory" ("MigrationId", "ProductVersion") +VALUES ('20260130221620_2.0.0-MajorVersionBump', '9.0.4'); + +COMMIT; `; var MIGRATION_SCRIPTS = { 1: `\uFEFFBEGIN TRANSACTION; @@ -2460,7 +2466,12 @@ CREATE INDEX "IX_TotpCodes_ItemId" ON "TotpCodes" ("ItemId"); COMMIT; INSERT INTO "__EFMigrationsHistory" ("MigrationId", "ProductVersion") -VALUES ('20251213111207_1.7.0-FieldBasedDataModelUpdate', '9.0.4');` +VALUES ('20251213111207_1.7.0-FieldBasedDataModelUpdate', '9.0.4');`, + 12: `\uFEFFBEGIN TRANSACTION; +INSERT INTO "__EFMigrationsHistory" ("MigrationId", "ProductVersion") +VALUES ('20260130221620_2.0.0-MajorVersionBump', '9.0.4'); + +COMMIT;` }; // src/sql/VaultVersions.ts @@ -2547,7 +2558,14 @@ var VAULT_VERSIONS = [ version: "1.7.0", description: "Update to Field-Based Data Model", releaseVersion: "0.26.0", - compatibleUpToVersion: "0.26.0" + compatibleUpToVersion: "0.25.0" + }, + { + revision: 13, + version: "2.0.0", + description: "Update to Field-Based Data Model", + releaseVersion: "0.26.1", + compatibleUpToVersion: "0.25.0" } ]; diff --git a/apps/server/AliasVault.Client/wwwroot/js/dist/core/vault/index.d.mts b/apps/server/AliasVault.Client/wwwroot/js/dist/core/vault/index.d.mts index 033a999f0..0ee327dbe 100644 --- a/apps/server/AliasVault.Client/wwwroot/js/dist/core/vault/index.d.mts +++ b/apps/server/AliasVault.Client/wwwroot/js/dist/core/vault/index.d.mts @@ -122,7 +122,7 @@ declare const VAULT_VERSIONS: VaultVersion[]; * Complete database schema SQL (latest version) * Auto-generated from EF Core migrations */ -declare const COMPLETE_SCHEMA_SQL = "\n\uFEFFCREATE TABLE IF NOT EXISTS \"__EFMigrationsHistory\" (\n \"MigrationId\" TEXT NOT NULL CONSTRAINT \"PK___EFMigrationsHistory\" PRIMARY KEY,\n \"ProductVersion\" TEXT NOT NULL\n);\n\nBEGIN TRANSACTION;\nCREATE TABLE \"Aliases\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_Aliases\" PRIMARY KEY,\n \"Gender\" VARCHAR NULL,\n \"FirstName\" VARCHAR NULL,\n \"LastName\" VARCHAR NULL,\n \"NickName\" VARCHAR NULL,\n \"BirthDate\" TEXT NOT NULL,\n \"AddressStreet\" VARCHAR NULL,\n \"AddressCity\" VARCHAR NULL,\n \"AddressState\" VARCHAR NULL,\n \"AddressZipCode\" VARCHAR NULL,\n \"AddressCountry\" VARCHAR NULL,\n \"Hobbies\" TEXT NULL,\n \"EmailPrefix\" TEXT NULL,\n \"PhoneMobile\" TEXT NULL,\n \"BankAccountIBAN\" TEXT NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"UpdatedAt\" TEXT NOT NULL\n);\n\nCREATE TABLE \"Services\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_Services\" PRIMARY KEY,\n \"Name\" TEXT NULL,\n \"Url\" TEXT NULL,\n \"Logo\" BLOB NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"UpdatedAt\" TEXT NOT NULL\n);\n\nCREATE TABLE \"Credentials\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_Credentials\" PRIMARY KEY,\n \"AliasId\" TEXT NOT NULL,\n \"Notes\" TEXT NULL,\n \"Username\" TEXT NOT NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"UpdatedAt\" TEXT NOT NULL,\n \"ServiceId\" TEXT NOT NULL,\n CONSTRAINT \"FK_Credentials_Aliases_AliasId\" FOREIGN KEY (\"AliasId\") REFERENCES \"Aliases\" (\"Id\") ON DELETE CASCADE,\n CONSTRAINT \"FK_Credentials_Services_ServiceId\" FOREIGN KEY (\"ServiceId\") REFERENCES \"Services\" (\"Id\") ON DELETE CASCADE\n);\n\nCREATE TABLE \"Attachment\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_Attachment\" PRIMARY KEY,\n \"Filename\" TEXT NOT NULL,\n \"Blob\" BLOB NOT NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"UpdatedAt\" TEXT NOT NULL,\n \"CredentialId\" TEXT NOT NULL,\n CONSTRAINT \"FK_Attachment_Credentials_CredentialId\" FOREIGN KEY (\"CredentialId\") REFERENCES \"Credentials\" (\"Id\") ON DELETE CASCADE\n);\n\nCREATE TABLE \"Passwords\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_Passwords\" PRIMARY KEY,\n \"Value\" TEXT NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"UpdatedAt\" TEXT NOT NULL,\n \"CredentialId\" TEXT NOT NULL,\n CONSTRAINT \"FK_Passwords_Credentials_CredentialId\" FOREIGN KEY (\"CredentialId\") REFERENCES \"Credentials\" (\"Id\") ON DELETE CASCADE\n);\n\nCREATE INDEX \"IX_Attachment_CredentialId\" ON \"Attachment\" (\"CredentialId\");\n\nCREATE INDEX \"IX_Credentials_AliasId\" ON \"Credentials\" (\"AliasId\");\n\nCREATE INDEX \"IX_Credentials_ServiceId\" ON \"Credentials\" (\"ServiceId\");\n\nCREATE INDEX \"IX_Passwords_CredentialId\" ON \"Passwords\" (\"CredentialId\");\n\nINSERT INTO \"__EFMigrationsHistory\" (\"MigrationId\", \"ProductVersion\")\nVALUES ('20240708094944_1.0.0-InitialMigration', '9.0.4');\n\nINSERT INTO \"__EFMigrationsHistory\" (\"MigrationId\", \"ProductVersion\")\nVALUES ('20240708224522_1.0.1-EmptyTestMigration', '9.0.4');\n\nALTER TABLE \"Aliases\" RENAME COLUMN \"EmailPrefix\" TO \"Email\";\n\nINSERT INTO \"__EFMigrationsHistory\" (\"MigrationId\", \"ProductVersion\")\nVALUES ('20240711204207_1.0.2-ChangeEmailColumn', '9.0.4');\n\nCREATE TABLE \"EncryptionKeys\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_EncryptionKeys\" PRIMARY KEY,\n \"PublicKey\" TEXT NOT NULL,\n \"PrivateKey\" TEXT NOT NULL,\n \"IsPrimary\" INTEGER NOT NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"UpdatedAt\" TEXT NOT NULL\n);\n\nINSERT INTO \"__EFMigrationsHistory\" (\"MigrationId\", \"ProductVersion\")\nVALUES ('20240729105618_1.1.0-AddPkiTables', '9.0.4');\n\nCREATE TABLE \"Settings\" (\n \"Key\" TEXT NOT NULL CONSTRAINT \"PK_Settings\" PRIMARY KEY,\n \"Value\" TEXT NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"UpdatedAt\" TEXT NOT NULL\n);\n\nINSERT INTO \"__EFMigrationsHistory\" (\"MigrationId\", \"ProductVersion\")\nVALUES ('20240805073413_1.2.0-AddSettingsTable', '9.0.4');\n\nCREATE TABLE \"ef_temp_Aliases\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_Aliases\" PRIMARY KEY,\n \"BirthDate\" TEXT NOT NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"Email\" TEXT NULL,\n \"FirstName\" VARCHAR NULL,\n \"Gender\" VARCHAR NULL,\n \"LastName\" VARCHAR NULL,\n \"NickName\" VARCHAR NULL,\n \"UpdatedAt\" TEXT NOT NULL\n);\n\nINSERT INTO \"ef_temp_Aliases\" (\"Id\", \"BirthDate\", \"CreatedAt\", \"Email\", \"FirstName\", \"Gender\", \"LastName\", \"NickName\", \"UpdatedAt\")\nSELECT \"Id\", \"BirthDate\", \"CreatedAt\", \"Email\", \"FirstName\", \"Gender\", \"LastName\", \"NickName\", \"UpdatedAt\"\nFROM \"Aliases\";\n\nCOMMIT;\n\nPRAGMA foreign_keys = 0;\n\nBEGIN TRANSACTION;\nDROP TABLE \"Aliases\";\n\nALTER TABLE \"ef_temp_Aliases\" RENAME TO \"Aliases\";\n\nCOMMIT;\n\nPRAGMA foreign_keys = 1;\n\nINSERT INTO \"__EFMigrationsHistory\" (\"MigrationId\", \"ProductVersion\")\nVALUES ('20240805122422_1.3.0-UpdateIdentityStructure', '9.0.4');\n\nBEGIN TRANSACTION;\nCREATE TABLE \"ef_temp_Credentials\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_Credentials\" PRIMARY KEY,\n \"AliasId\" TEXT NOT NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"Notes\" TEXT NULL,\n \"ServiceId\" TEXT NOT NULL,\n \"UpdatedAt\" TEXT NOT NULL,\n \"Username\" TEXT NULL,\n CONSTRAINT \"FK_Credentials_Aliases_AliasId\" FOREIGN KEY (\"AliasId\") REFERENCES \"Aliases\" (\"Id\") ON DELETE CASCADE,\n CONSTRAINT \"FK_Credentials_Services_ServiceId\" FOREIGN KEY (\"ServiceId\") REFERENCES \"Services\" (\"Id\") ON DELETE CASCADE\n);\n\nINSERT INTO \"ef_temp_Credentials\" (\"Id\", \"AliasId\", \"CreatedAt\", \"Notes\", \"ServiceId\", \"UpdatedAt\", \"Username\")\nSELECT \"Id\", \"AliasId\", \"CreatedAt\", \"Notes\", \"ServiceId\", \"UpdatedAt\", \"Username\"\nFROM \"Credentials\";\n\nCOMMIT;\n\nPRAGMA foreign_keys = 0;\n\nBEGIN TRANSACTION;\nDROP TABLE \"Credentials\";\n\nALTER TABLE \"ef_temp_Credentials\" RENAME TO \"Credentials\";\n\nCOMMIT;\n\nPRAGMA foreign_keys = 1;\n\nBEGIN TRANSACTION;\nCREATE INDEX \"IX_Credentials_AliasId\" ON \"Credentials\" (\"AliasId\");\n\nCREATE INDEX \"IX_Credentials_ServiceId\" ON \"Credentials\" (\"ServiceId\");\n\nCOMMIT;\n\nINSERT INTO \"__EFMigrationsHistory\" (\"MigrationId\", \"ProductVersion\")\nVALUES ('20240812141727_1.3.1-MakeUsernameOptional', '9.0.4');\n\nBEGIN TRANSACTION;\nALTER TABLE \"Settings\" ADD \"IsDeleted\" INTEGER NOT NULL DEFAULT 0;\n\nALTER TABLE \"Services\" ADD \"IsDeleted\" INTEGER NOT NULL DEFAULT 0;\n\nALTER TABLE \"Passwords\" ADD \"IsDeleted\" INTEGER NOT NULL DEFAULT 0;\n\nALTER TABLE \"EncryptionKeys\" ADD \"IsDeleted\" INTEGER NOT NULL DEFAULT 0;\n\nALTER TABLE \"Credentials\" ADD \"IsDeleted\" INTEGER NOT NULL DEFAULT 0;\n\nALTER TABLE \"Attachment\" ADD \"IsDeleted\" INTEGER NOT NULL DEFAULT 0;\n\nALTER TABLE \"Aliases\" ADD \"IsDeleted\" INTEGER NOT NULL DEFAULT 0;\n\nINSERT INTO \"__EFMigrationsHistory\" (\"MigrationId\", \"ProductVersion\")\nVALUES ('20240916105320_1.4.0-AddSyncSupport', '9.0.4');\n\nALTER TABLE \"Attachment\" RENAME TO \"Attachments\";\n\nCREATE TABLE \"ef_temp_Attachments\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_Attachments\" PRIMARY KEY,\n \"Blob\" BLOB NOT NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"CredentialId\" TEXT NOT NULL,\n \"Filename\" TEXT NOT NULL,\n \"IsDeleted\" INTEGER NOT NULL,\n \"UpdatedAt\" TEXT NOT NULL,\n CONSTRAINT \"FK_Attachments_Credentials_CredentialId\" FOREIGN KEY (\"CredentialId\") REFERENCES \"Credentials\" (\"Id\") ON DELETE CASCADE\n);\n\nINSERT INTO \"ef_temp_Attachments\" (\"Id\", \"Blob\", \"CreatedAt\", \"CredentialId\", \"Filename\", \"IsDeleted\", \"UpdatedAt\")\nSELECT \"Id\", \"Blob\", \"CreatedAt\", \"CredentialId\", \"Filename\", \"IsDeleted\", \"UpdatedAt\"\nFROM \"Attachments\";\n\nCOMMIT;\n\nPRAGMA foreign_keys = 0;\n\nBEGIN TRANSACTION;\nDROP TABLE \"Attachments\";\n\nALTER TABLE \"ef_temp_Attachments\" RENAME TO \"Attachments\";\n\nCOMMIT;\n\nPRAGMA foreign_keys = 1;\n\nBEGIN TRANSACTION;\nCREATE INDEX \"IX_Attachments_CredentialId\" ON \"Attachments\" (\"CredentialId\");\n\nCOMMIT;\n\nINSERT INTO \"__EFMigrationsHistory\" (\"MigrationId\", \"ProductVersion\")\nVALUES ('20240917191243_1.4.1-RenameAttachmentsPlural', '9.0.4');\n\nBEGIN TRANSACTION;\nCREATE TABLE \"TotpCodes\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_TotpCodes\" PRIMARY KEY,\n \"Name\" TEXT NOT NULL,\n \"SecretKey\" TEXT NOT NULL,\n \"CredentialId\" TEXT NOT NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"UpdatedAt\" TEXT NOT NULL,\n \"IsDeleted\" INTEGER NOT NULL,\n CONSTRAINT \"FK_TotpCodes_Credentials_CredentialId\" FOREIGN KEY (\"CredentialId\") REFERENCES \"Credentials\" (\"Id\") ON DELETE CASCADE\n);\n\nCREATE INDEX \"IX_TotpCodes_CredentialId\" ON \"TotpCodes\" (\"CredentialId\");\n\nINSERT INTO \"__EFMigrationsHistory\" (\"MigrationId\", \"ProductVersion\")\nVALUES ('20250310131554_1.5.0-AddTotpCodes', '9.0.4');\n\n\nPRAGMA foreign_keys = OFF;\n\n-- Clean up any existing temp tables first\nDROP TABLE IF EXISTS \"__EFMigrationsHistory_temp\";\nDROP TABLE IF EXISTS \"Aliases_temp\";\nDROP TABLE IF EXISTS \"Services_temp\";\nDROP TABLE IF EXISTS \"EncryptionKeys_temp\";\nDROP TABLE IF EXISTS \"Settings_temp\";\nDROP TABLE IF EXISTS \"Credentials_temp\";\nDROP TABLE IF EXISTS \"Attachments_temp\";\nDROP TABLE IF EXISTS \"Passwords_temp\";\nDROP TABLE IF EXISTS \"TotpCodes_temp\";\n\n-- Create backup tables for all data\nCREATE TABLE \"__EFMigrationsHistory_temp\" AS SELECT * FROM \"__EFMigrationsHistory\";\nCREATE TABLE \"Aliases_temp\" AS SELECT * FROM \"Aliases\";\nCREATE TABLE \"Services_temp\" AS SELECT * FROM \"Services\";\nCREATE TABLE \"EncryptionKeys_temp\" AS SELECT * FROM \"EncryptionKeys\";\nCREATE TABLE \"Settings_temp\" AS SELECT * FROM \"Settings\";\nCREATE TABLE \"Credentials_temp\" AS SELECT * FROM \"Credentials\";\nCREATE TABLE \"Attachments_temp\" AS SELECT * FROM \"Attachments\";\nCREATE TABLE \"Passwords_temp\" AS SELECT * FROM \"Passwords\";\nCREATE TABLE \"TotpCodes_temp\" AS SELECT * FROM \"TotpCodes\";\n\n-- Delete orphaned records that do not have a valid FK to the credential object\nDELETE FROM \"Attachments_temp\" WHERE \"CredentialId\" NOT IN (SELECT \"Id\" FROM \"Credentials_temp\");\nDELETE FROM \"Passwords_temp\" WHERE \"CredentialId\" NOT IN (SELECT \"Id\" FROM \"Credentials_temp\");\nDELETE FROM \"TotpCodes_temp\" WHERE \"CredentialId\" NOT IN (SELECT \"Id\" FROM \"Credentials_temp\");\n\n-- Delete orphaned credentials that do not have valid FKs to alias or service objects\nDELETE FROM \"Credentials_temp\" WHERE \"AliasId\" NOT IN (SELECT \"Id\" FROM \"Aliases_temp\");\nDELETE FROM \"Credentials_temp\" WHERE \"ServiceId\" NOT IN (SELECT \"Id\" FROM \"Services_temp\");\n\n-- After cleaning credentials, clean dependent tables again in case we removed credentials\nDELETE FROM \"Attachments_temp\" WHERE \"CredentialId\" NOT IN (SELECT \"Id\" FROM \"Credentials_temp\");\nDELETE FROM \"Passwords_temp\" WHERE \"CredentialId\" NOT IN (SELECT \"Id\" FROM \"Credentials_temp\");\nDELETE FROM \"TotpCodes_temp\" WHERE \"CredentialId\" NOT IN (SELECT \"Id\" FROM \"Credentials_temp\");\n\n-- Drop all existing tables\nDROP TABLE \"TotpCodes\";\nDROP TABLE \"Passwords\";\nDROP TABLE \"Attachments\";\nDROP TABLE \"Credentials\";\nDROP TABLE \"Settings\";\nDROP TABLE \"EncryptionKeys\";\nDROP TABLE \"Services\";\nDROP TABLE \"Aliases\";\nDROP TABLE \"__EFMigrationsHistory\";\n\n-- Recreate tables with proper constraints (no dependencies first)\nCREATE TABLE \"__EFMigrationsHistory\" (\n \"MigrationId\" TEXT NOT NULL CONSTRAINT \"PK___EFMigrationsHistory\" PRIMARY KEY,\n \"ProductVersion\" TEXT NOT NULL\n);\n\nCREATE TABLE \"Aliases\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_Aliases\" PRIMARY KEY,\n \"BirthDate\" TEXT NOT NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"Email\" TEXT NULL,\n \"FirstName\" VARCHAR NULL,\n \"Gender\" VARCHAR NULL,\n \"LastName\" VARCHAR NULL,\n \"NickName\" VARCHAR NULL,\n \"UpdatedAt\" TEXT NOT NULL,\n \"IsDeleted\" INTEGER NOT NULL DEFAULT 0\n);\n\nCREATE TABLE \"Services\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_Services\" PRIMARY KEY,\n \"Name\" TEXT NULL,\n \"Url\" TEXT NULL,\n \"Logo\" BLOB NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"UpdatedAt\" TEXT NOT NULL,\n \"IsDeleted\" INTEGER NOT NULL DEFAULT 0\n);\n\nCREATE TABLE \"EncryptionKeys\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_EncryptionKeys\" PRIMARY KEY,\n \"PublicKey\" TEXT NOT NULL,\n \"PrivateKey\" TEXT NOT NULL,\n \"IsPrimary\" INTEGER NOT NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"UpdatedAt\" TEXT NOT NULL,\n \"IsDeleted\" INTEGER NOT NULL DEFAULT 0\n);\n\nCREATE TABLE \"Settings\" (\n \"Key\" TEXT NOT NULL CONSTRAINT \"PK_Settings\" PRIMARY KEY,\n \"Value\" TEXT NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"UpdatedAt\" TEXT NOT NULL,\n \"IsDeleted\" INTEGER NOT NULL DEFAULT 0\n);\n\n-- Tables with foreign keys\nCREATE TABLE \"Credentials\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_Credentials\" PRIMARY KEY,\n \"AliasId\" TEXT NOT NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"Notes\" TEXT NULL,\n \"ServiceId\" TEXT NOT NULL,\n \"UpdatedAt\" TEXT NOT NULL,\n \"Username\" TEXT NULL,\n \"IsDeleted\" INTEGER NOT NULL DEFAULT 0,\n CONSTRAINT \"FK_Credentials_Aliases_AliasId\" FOREIGN KEY (\"AliasId\") REFERENCES \"Aliases\" (\"Id\") ON DELETE CASCADE,\n CONSTRAINT \"FK_Credentials_Services_ServiceId\" FOREIGN KEY (\"ServiceId\") REFERENCES \"Services\" (\"Id\") ON DELETE CASCADE\n);\n\nCREATE TABLE \"Attachments\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_Attachments\" PRIMARY KEY,\n \"Blob\" BLOB NOT NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"CredentialId\" TEXT NOT NULL,\n \"Filename\" TEXT NOT NULL,\n \"IsDeleted\" INTEGER NOT NULL DEFAULT 0,\n \"UpdatedAt\" TEXT NOT NULL,\n CONSTRAINT \"FK_Attachments_Credentials_CredentialId\" FOREIGN KEY (\"CredentialId\") REFERENCES \"Credentials\" (\"Id\") ON DELETE CASCADE\n);\n\nCREATE TABLE \"Passwords\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_Passwords\" PRIMARY KEY,\n \"Value\" TEXT NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"UpdatedAt\" TEXT NOT NULL,\n \"CredentialId\" TEXT NOT NULL,\n \"IsDeleted\" INTEGER NOT NULL DEFAULT 0,\n CONSTRAINT \"FK_Passwords_Credentials_CredentialId\" FOREIGN KEY (\"CredentialId\") REFERENCES \"Credentials\" (\"Id\") ON DELETE CASCADE\n);\n\nCREATE TABLE \"TotpCodes\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_TotpCodes\" PRIMARY KEY,\n \"Name\" TEXT NOT NULL,\n \"SecretKey\" TEXT NOT NULL,\n \"CredentialId\" TEXT NOT NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"UpdatedAt\" TEXT NOT NULL,\n \"IsDeleted\" INTEGER NOT NULL DEFAULT 0,\n CONSTRAINT \"FK_TotpCodes_Credentials_CredentialId\" FOREIGN KEY (\"CredentialId\") REFERENCES \"Credentials\" (\"Id\") ON DELETE CASCADE\n);\n\n\n-- Restore data from temp tables\nINSERT INTO \"__EFMigrationsHistory\" SELECT * FROM \"__EFMigrationsHistory_temp\";\nINSERT INTO \"Aliases\" SELECT * FROM \"Aliases_temp\";\nINSERT INTO \"Services\" SELECT * FROM \"Services_temp\";\nINSERT INTO \"EncryptionKeys\" SELECT * FROM \"EncryptionKeys_temp\";\nINSERT INTO \"Settings\" SELECT * FROM \"Settings_temp\";\nINSERT INTO \"Credentials\" SELECT * FROM \"Credentials_temp\";\nINSERT INTO \"Attachments\" SELECT * FROM \"Attachments_temp\";\nINSERT INTO \"Passwords\" SELECT * FROM \"Passwords_temp\";\nINSERT INTO \"TotpCodes\" SELECT * FROM \"TotpCodes_temp\";\n\n-- =====================================================================================\n-- Date Format Normalization Migration\n-- =====================================================================================\n-- This migration normalizes ALL date fields to the standard format: 'yyyy-MM-dd HH:mm:ss.fff'\n-- Previously the different clients used different date formats which complicate date parsing.\n-- From version 0.24.0 onwards, all new dates are stored in this standard format.\n\n-- Update Aliases table (CreatedAt, UpdatedAt, BirthDate)\nUPDATE \"Aliases\" SET \"CreatedAt\" =\n CASE\n -- Already in correct format (yyyy-MM-dd HH:mm:ss.fff) - no change\n WHEN \"CreatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9] [0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9][0-9][0-9]'\n THEN \"CreatedAt\"\n\n -- ISO 8601 with milliseconds (yyyy-MM-ddTHH:mm:ss.fffZ) -> Replace T with space, remove Z and everything after .fff\n WHEN \"CreatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]T[0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9]*'\n THEN substr(\"CreatedAt\", 1, 10) || ' ' || substr(\"CreatedAt\", 12, 12)\n\n -- Without milliseconds (yyyy-MM-dd HH:mm:ss or yyyy-MM-ddTHH:mm:ssZ) -> Add .000\n WHEN \"CreatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9][T ][0-9][0-9]:[0-9][0-9]:[0-9][0-9]*'\n THEN substr(\"CreatedAt\", 1, 10) || ' ' || substr(replace(\"CreatedAt\", 'T', ' '), 12, 8) || '.000'\n\n -- Fallback: if none match, keep as-is (edge case)\n ELSE \"CreatedAt\"\n END;\n\nUPDATE \"Aliases\" SET \"UpdatedAt\" =\n CASE\n WHEN \"UpdatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9] [0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9][0-9][0-9]'\n THEN \"UpdatedAt\"\n WHEN \"UpdatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]T[0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9]*'\n THEN substr(\"UpdatedAt\", 1, 10) || ' ' || substr(\"UpdatedAt\", 12, 12)\n WHEN \"UpdatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9][T ][0-9][0-9]:[0-9][0-9]:[0-9][0-9]*'\n THEN substr(\"UpdatedAt\", 1, 10) || ' ' || substr(replace(\"UpdatedAt\", 'T', ' '), 12, 8) || '.000'\n ELSE \"UpdatedAt\"\n END;\n\n-- BirthDate: Always set time to 00:00:00 (no milliseconds for birth dates)\nUPDATE \"Aliases\" SET \"BirthDate\" =\n CASE\n -- If empty or already '0001-01-01 00:00:00', keep as-is\n WHEN \"BirthDate\" = '' OR \"BirthDate\" = '0001-01-01 00:00:00'\n THEN \"BirthDate\"\n\n -- If already in correct format (yyyy-MM-dd 00:00:00), keep as-is\n WHEN \"BirthDate\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9] 00:00:00'\n THEN \"BirthDate\"\n\n -- Extract date part and set time to 00:00:00\n WHEN \"BirthDate\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]*'\n THEN substr(\"BirthDate\", 1, 10) || ' 00:00:00'\n\n -- Fallback\n ELSE \"BirthDate\"\n END;\n\n-- Update Services table (CreatedAt, UpdatedAt)\nUPDATE \"Services\" SET \"CreatedAt\" =\n CASE\n WHEN \"CreatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9] [0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9][0-9][0-9]'\n THEN \"CreatedAt\"\n WHEN \"CreatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]T[0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9]*'\n THEN substr(\"CreatedAt\", 1, 10) || ' ' || substr(\"CreatedAt\", 12, 12)\n WHEN \"CreatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9][T ][0-9][0-9]:[0-9][0-9]:[0-9][0-9]*'\n THEN substr(\"CreatedAt\", 1, 10) || ' ' || substr(replace(\"CreatedAt\", 'T', ' '), 12, 8) || '.000'\n ELSE \"CreatedAt\"\n END;\n\nUPDATE \"Services\" SET \"UpdatedAt\" =\n CASE\n WHEN \"UpdatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9] [0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9][0-9][0-9]'\n THEN \"UpdatedAt\"\n WHEN \"UpdatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]T[0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9]*'\n THEN substr(\"UpdatedAt\", 1, 10) || ' ' || substr(\"UpdatedAt\", 12, 12)\n WHEN \"UpdatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9][T ][0-9][0-9]:[0-9][0-9]:[0-9][0-9]*'\n THEN substr(\"UpdatedAt\", 1, 10) || ' ' || substr(replace(\"UpdatedAt\", 'T', ' '), 12, 8) || '.000'\n ELSE \"UpdatedAt\"\n END;\n\n-- Update EncryptionKeys table (CreatedAt, UpdatedAt)\nUPDATE \"EncryptionKeys\" SET \"CreatedAt\" =\n CASE\n WHEN \"CreatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9] [0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9][0-9][0-9]'\n THEN \"CreatedAt\"\n WHEN \"CreatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]T[0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9]*'\n THEN substr(\"CreatedAt\", 1, 10) || ' ' || substr(\"CreatedAt\", 12, 12)\n WHEN \"CreatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9][T ][0-9][0-9]:[0-9][0-9]:[0-9][0-9]*'\n THEN substr(\"CreatedAt\", 1, 10) || ' ' || substr(replace(\"CreatedAt\", 'T', ' '), 12, 8) || '.000'\n ELSE \"CreatedAt\"\n END;\n\nUPDATE \"EncryptionKeys\" SET \"UpdatedAt\" =\n CASE\n WHEN \"UpdatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9] [0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9][0-9][0-9]'\n THEN \"UpdatedAt\"\n WHEN \"UpdatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]T[0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9]*'\n THEN substr(\"UpdatedAt\", 1, 10) || ' ' || substr(\"UpdatedAt\", 12, 12)\n WHEN \"UpdatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9][T ][0-9][0-9]:[0-9][0-9]:[0-9][0-9]*'\n THEN substr(\"UpdatedAt\", 1, 10) || ' ' || substr(replace(\"UpdatedAt\", 'T', ' '), 12, 8) || '.000'\n ELSE \"UpdatedAt\"\n END;\n\n-- Update Settings table (CreatedAt, UpdatedAt)\nUPDATE \"Settings\" SET \"CreatedAt\" =\n CASE\n WHEN \"CreatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9] [0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9][0-9][0-9]'\n THEN \"CreatedAt\"\n WHEN \"CreatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]T[0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9]*'\n THEN substr(\"CreatedAt\", 1, 10) || ' ' || substr(\"CreatedAt\", 12, 12)\n WHEN \"CreatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9][T ][0-9][0-9]:[0-9][0-9]:[0-9][0-9]*'\n THEN substr(\"CreatedAt\", 1, 10) || ' ' || substr(replace(\"CreatedAt\", 'T', ' '), 12, 8) || '.000'\n ELSE \"CreatedAt\"\n END;\n\nUPDATE \"Settings\" SET \"UpdatedAt\" =\n CASE\n WHEN \"UpdatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9] [0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9][0-9][0-9]'\n THEN \"UpdatedAt\"\n WHEN \"UpdatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]T[0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9]*'\n THEN substr(\"UpdatedAt\", 1, 10) || ' ' || substr(\"UpdatedAt\", 12, 12)\n WHEN \"UpdatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9][T ][0-9][0-9]:[0-9][0-9]:[0-9][0-9]*'\n THEN substr(\"UpdatedAt\", 1, 10) || ' ' || substr(replace(\"UpdatedAt\", 'T', ' '), 12, 8) || '.000'\n ELSE \"UpdatedAt\"\n END;\n\n-- Update Credentials table (CreatedAt, UpdatedAt)\nUPDATE \"Credentials\" SET \"CreatedAt\" =\n CASE\n WHEN \"CreatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9] [0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9][0-9][0-9]'\n THEN \"CreatedAt\"\n WHEN \"CreatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]T[0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9]*'\n THEN substr(\"CreatedAt\", 1, 10) || ' ' || substr(\"CreatedAt\", 12, 12)\n WHEN \"CreatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9][T ][0-9][0-9]:[0-9][0-9]:[0-9][0-9]*'\n THEN substr(\"CreatedAt\", 1, 10) || ' ' || substr(replace(\"CreatedAt\", 'T', ' '), 12, 8) || '.000'\n ELSE \"CreatedAt\"\n END;\n\nUPDATE \"Credentials\" SET \"UpdatedAt\" =\n CASE\n WHEN \"UpdatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9] [0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9][0-9][0-9]'\n THEN \"UpdatedAt\"\n WHEN \"UpdatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]T[0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9]*'\n THEN substr(\"UpdatedAt\", 1, 10) || ' ' || substr(\"UpdatedAt\", 12, 12)\n WHEN \"UpdatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9][T ][0-9][0-9]:[0-9][0-9]:[0-9][0-9]*'\n THEN substr(\"UpdatedAt\", 1, 10) || ' ' || substr(replace(\"UpdatedAt\", 'T', ' '), 12, 8) || '.000'\n ELSE \"UpdatedAt\"\n END;\n\n-- Update Attachments table (CreatedAt, UpdatedAt)\nUPDATE \"Attachments\" SET \"CreatedAt\" =\n CASE\n WHEN \"CreatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9] [0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9][0-9][0-9]'\n THEN \"CreatedAt\"\n WHEN \"CreatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]T[0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9]*'\n THEN substr(\"CreatedAt\", 1, 10) || ' ' || substr(\"CreatedAt\", 12, 12)\n WHEN \"CreatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9][T ][0-9][0-9]:[0-9][0-9]:[0-9][0-9]*'\n THEN substr(\"CreatedAt\", 1, 10) || ' ' || substr(replace(\"CreatedAt\", 'T', ' '), 12, 8) || '.000'\n ELSE \"CreatedAt\"\n END;\n\nUPDATE \"Attachments\" SET \"UpdatedAt\" =\n CASE\n WHEN \"UpdatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9] [0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9][0-9][0-9]'\n THEN \"UpdatedAt\"\n WHEN \"UpdatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]T[0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9]*'\n THEN substr(\"UpdatedAt\", 1, 10) || ' ' || substr(\"UpdatedAt\", 12, 12)\n WHEN \"UpdatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9][T ][0-9][0-9]:[0-9][0-9]:[0-9][0-9]*'\n THEN substr(\"UpdatedAt\", 1, 10) || ' ' || substr(replace(\"UpdatedAt\", 'T', ' '), 12, 8) || '.000'\n ELSE \"UpdatedAt\"\n END;\n\n-- Update Passwords table (CreatedAt, UpdatedAt)\nUPDATE \"Passwords\" SET \"CreatedAt\" =\n CASE\n WHEN \"CreatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9] [0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9][0-9][0-9]'\n THEN \"CreatedAt\"\n WHEN \"CreatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]T[0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9]*'\n THEN substr(\"CreatedAt\", 1, 10) || ' ' || substr(\"CreatedAt\", 12, 12)\n WHEN \"CreatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9][T ][0-9][0-9]:[0-9][0-9]:[0-9][0-9]*'\n THEN substr(\"CreatedAt\", 1, 10) || ' ' || substr(replace(\"CreatedAt\", 'T', ' '), 12, 8) || '.000'\n ELSE \"CreatedAt\"\n END;\n\nUPDATE \"Passwords\" SET \"UpdatedAt\" =\n CASE\n WHEN \"UpdatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9] [0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9][0-9][0-9]'\n THEN \"UpdatedAt\"\n WHEN \"UpdatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]T[0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9]*'\n THEN substr(\"UpdatedAt\", 1, 10) || ' ' || substr(\"UpdatedAt\", 12, 12)\n WHEN \"UpdatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9][T ][0-9][0-9]:[0-9][0-9]:[0-9][0-9]*'\n THEN substr(\"UpdatedAt\", 1, 10) || ' ' || substr(replace(\"UpdatedAt\", 'T', ' '), 12, 8) || '.000'\n ELSE \"UpdatedAt\"\n END;\n\n-- Update TotpCodes table (CreatedAt, UpdatedAt)\nUPDATE \"TotpCodes\" SET \"CreatedAt\" =\n CASE\n WHEN \"CreatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9] [0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9][0-9][0-9]'\n THEN \"CreatedAt\"\n WHEN \"CreatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]T[0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9]*'\n THEN substr(\"CreatedAt\", 1, 10) || ' ' || substr(\"CreatedAt\", 12, 12)\n WHEN \"CreatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9][T ][0-9][0-9]:[0-9][0-9]:[0-9][0-9]*'\n THEN substr(\"CreatedAt\", 1, 10) || ' ' || substr(replace(\"CreatedAt\", 'T', ' '), 12, 8) || '.000'\n ELSE \"CreatedAt\"\n END;\n\nUPDATE \"TotpCodes\" SET \"UpdatedAt\" =\n CASE\n WHEN \"UpdatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9] [0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9][0-9][0-9]'\n THEN \"UpdatedAt\"\n WHEN \"UpdatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]T[0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9]*'\n THEN substr(\"UpdatedAt\", 1, 10) || ' ' || substr(\"UpdatedAt\", 12, 12)\n WHEN \"UpdatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9][T ][0-9][0-9]:[0-9][0-9]:[0-9][0-9]*'\n THEN substr(\"UpdatedAt\", 1, 10) || ' ' || substr(replace(\"UpdatedAt\", 'T', ' '), 12, 8) || '.000'\n ELSE \"UpdatedAt\"\n END;\n\n-- =====================================================================================\n-- End of Date Format Normalization Migration\n-- =====================================================================================\n\n-- Recreate indexes\nCREATE INDEX \"IX_Credentials_AliasId\" ON \"Credentials\" (\"AliasId\");\nCREATE INDEX \"IX_Credentials_ServiceId\" ON \"Credentials\" (\"ServiceId\");\nCREATE INDEX \"IX_Attachments_CredentialId\" ON \"Attachments\" (\"CredentialId\");\nCREATE INDEX \"IX_Passwords_CredentialId\" ON \"Passwords\" (\"CredentialId\");\nCREATE INDEX \"IX_TotpCodes_CredentialId\" ON \"TotpCodes\" (\"CredentialId\");\n\n-- Clean up temp tables\nDROP TABLE \"__EFMigrationsHistory_temp\";\nDROP TABLE \"Aliases_temp\";\nDROP TABLE \"Services_temp\";\nDROP TABLE \"EncryptionKeys_temp\";\nDROP TABLE \"Settings_temp\";\nDROP TABLE \"Credentials_temp\";\nDROP TABLE \"Attachments_temp\";\nDROP TABLE \"Passwords_temp\";\nDROP TABLE \"TotpCodes_temp\";\n\nPRAGMA foreign_keys = ON;\n\n\nCREATE TABLE \"Passkeys\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_Passkeys\" PRIMARY KEY,\n \"RpId\" TEXT COLLATE NOCASE NOT NULL,\n \"UserHandle\" BLOB NOT NULL,\n \"PublicKey\" TEXT NOT NULL,\n \"PrivateKey\" TEXT NOT NULL,\n \"PrfKey\" BLOB NULL,\n \"DisplayName\" TEXT NOT NULL,\n \"AdditionalData\" BLOB NULL,\n \"CredentialId\" TEXT NOT NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"UpdatedAt\" TEXT NOT NULL,\n \"IsDeleted\" INTEGER NOT NULL,\n CONSTRAINT \"FK_Passkeys_Credentials_CredentialId\" FOREIGN KEY (\"CredentialId\") REFERENCES \"Credentials\" (\"Id\") ON DELETE CASCADE\n);\n\nCREATE INDEX \"IX_Passkeys_CredentialId\" ON \"Passkeys\" (\"CredentialId\");\n\nCREATE INDEX \"IX_Passkeys_RpId\" ON \"Passkeys\" (\"RpId\");\n\nINSERT INTO \"__EFMigrationsHistory\" (\"MigrationId\", \"ProductVersion\")\nVALUES ('20251014122838_1.6.0-AddPasskeys', '9.0.4');\n\nALTER TABLE \"TotpCodes\" RENAME COLUMN \"CredentialId\" TO \"ItemId\";\n\nDROP INDEX IF EXISTS \"IX_TotpCodes_CredentialId\";\n\nCREATE INDEX IF NOT EXISTS \"IX_TotpCodes_ItemId\" ON \"TotpCodes\" (\"ItemId\");\n\nALTER TABLE \"Passkeys\" RENAME COLUMN \"CredentialId\" TO \"ItemId\";\n\nDROP INDEX IF EXISTS \"IX_Passkeys_CredentialId\";\n\nCREATE INDEX IF NOT EXISTS \"IX_Passkeys_ItemId\" ON \"Passkeys\" (\"ItemId\");\n\nALTER TABLE \"Attachments\" RENAME COLUMN \"CredentialId\" TO \"ItemId\";\n\nDROP INDEX IF EXISTS \"IX_Attachments_CredentialId\";\n\nCREATE INDEX IF NOT EXISTS \"IX_Attachments_ItemId\" ON \"Attachments\" (\"ItemId\");\n\nCREATE TABLE \"FieldDefinitions\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_FieldDefinitions\" PRIMARY KEY,\n \"FieldType\" TEXT NOT NULL,\n \"Label\" TEXT NOT NULL,\n \"IsMultiValue\" INTEGER NOT NULL,\n \"IsHidden\" INTEGER NOT NULL,\n \"EnableHistory\" INTEGER NOT NULL,\n \"Weight\" INTEGER NOT NULL,\n \"ApplicableToTypes\" TEXT NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"UpdatedAt\" TEXT NOT NULL,\n \"IsDeleted\" INTEGER NOT NULL\n);\n\nCREATE TABLE \"Folders\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_Folders\" PRIMARY KEY,\n \"Name\" TEXT NOT NULL,\n \"ParentFolderId\" TEXT NULL,\n \"Weight\" INTEGER NOT NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"UpdatedAt\" TEXT NOT NULL,\n \"IsDeleted\" INTEGER NOT NULL,\n CONSTRAINT \"FK_Folders_Folders_ParentFolderId\" FOREIGN KEY (\"ParentFolderId\") REFERENCES \"Folders\" (\"Id\") ON DELETE CASCADE\n);\n\nCREATE TABLE \"Logos\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_Logos\" PRIMARY KEY,\n \"Source\" TEXT NOT NULL,\n \"FileData\" BLOB NULL,\n \"MimeType\" TEXT NULL,\n \"FetchedAt\" TEXT NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"UpdatedAt\" TEXT NOT NULL,\n \"IsDeleted\" INTEGER NOT NULL\n);\n\nCREATE TABLE \"Tags\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_Tags\" PRIMARY KEY,\n \"Name\" TEXT NOT NULL,\n \"Color\" TEXT NULL,\n \"DisplayOrder\" INTEGER NOT NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"UpdatedAt\" TEXT NOT NULL,\n \"IsDeleted\" INTEGER NOT NULL\n);\n\nCREATE TABLE \"Items\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_Items\" PRIMARY KEY,\n \"Name\" TEXT NULL,\n \"ItemType\" TEXT NOT NULL,\n \"LogoId\" TEXT NULL,\n \"DeletedAt\" TEXT NULL,\n \"FolderId\" TEXT NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"UpdatedAt\" TEXT NOT NULL,\n \"IsDeleted\" INTEGER NOT NULL,\n CONSTRAINT \"FK_Items_Folders_FolderId\" FOREIGN KEY (\"FolderId\") REFERENCES \"Folders\" (\"Id\") ON DELETE SET NULL,\n CONSTRAINT \"FK_Items_Logos_LogoId\" FOREIGN KEY (\"LogoId\") REFERENCES \"Logos\" (\"Id\") ON DELETE SET NULL\n);\n\nCREATE TABLE \"FieldHistories\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_FieldHistories\" PRIMARY KEY,\n \"ItemId\" TEXT NOT NULL,\n \"FieldDefinitionId\" TEXT NULL,\n \"FieldKey\" TEXT NULL,\n \"ValueSnapshot\" TEXT NOT NULL,\n \"ChangedAt\" TEXT NOT NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"UpdatedAt\" TEXT NOT NULL,\n \"IsDeleted\" INTEGER NOT NULL,\n CONSTRAINT \"FK_FieldHistories_FieldDefinitions_FieldDefinitionId\" FOREIGN KEY (\"FieldDefinitionId\") REFERENCES \"FieldDefinitions\" (\"Id\") ON DELETE CASCADE,\n CONSTRAINT \"FK_FieldHistories_Items_ItemId\" FOREIGN KEY (\"ItemId\") REFERENCES \"Items\" (\"Id\") ON DELETE CASCADE\n);\n\nCREATE TABLE \"FieldValues\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_FieldValues\" PRIMARY KEY,\n \"ItemId\" TEXT NOT NULL,\n \"FieldDefinitionId\" TEXT NULL,\n \"FieldKey\" TEXT NULL,\n \"Value\" TEXT NULL,\n \"Weight\" INTEGER NOT NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"UpdatedAt\" TEXT NOT NULL,\n \"IsDeleted\" INTEGER NOT NULL,\n CONSTRAINT \"FK_FieldValues_FieldDefinitions_FieldDefinitionId\" FOREIGN KEY (\"FieldDefinitionId\") REFERENCES \"FieldDefinitions\" (\"Id\") ON DELETE CASCADE,\n CONSTRAINT \"FK_FieldValues_Items_ItemId\" FOREIGN KEY (\"ItemId\") REFERENCES \"Items\" (\"Id\") ON DELETE CASCADE\n);\n\nCREATE TABLE \"ItemTags\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_ItemTags\" PRIMARY KEY,\n \"ItemId\" TEXT NOT NULL,\n \"TagId\" TEXT NOT NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"UpdatedAt\" TEXT NOT NULL,\n \"IsDeleted\" INTEGER NOT NULL,\n CONSTRAINT \"FK_ItemTags_Items_ItemId\" FOREIGN KEY (\"ItemId\") REFERENCES \"Items\" (\"Id\") ON DELETE CASCADE,\n CONSTRAINT \"FK_ItemTags_Tags_TagId\" FOREIGN KEY (\"TagId\") REFERENCES \"Tags\" (\"Id\") ON DELETE CASCADE\n);\n\nCREATE INDEX \"IX_FieldHistories_FieldDefinitionId\" ON \"FieldHistories\" (\"FieldDefinitionId\");\n\nCREATE INDEX \"IX_FieldHistories_ItemId\" ON \"FieldHistories\" (\"ItemId\");\n\nCREATE INDEX \"IX_FieldValues_FieldDefinitionId\" ON \"FieldValues\" (\"FieldDefinitionId\");\n\nCREATE INDEX \"IX_FieldValues_FieldKey\" ON \"FieldValues\" (\"FieldKey\");\n\nCREATE INDEX \"IX_FieldValues_ItemId\" ON \"FieldValues\" (\"ItemId\");\n\nCREATE INDEX \"IX_FieldValues_ItemId_FieldDefinitionId_Weight\" ON \"FieldValues\" (\"ItemId\", \"FieldDefinitionId\", \"Weight\");\n\nCREATE INDEX \"IX_FieldValues_ItemId_FieldKey\" ON \"FieldValues\" (\"ItemId\", \"FieldKey\");\n\nCREATE INDEX \"IX_Folders_ParentFolderId\" ON \"Folders\" (\"ParentFolderId\");\n\nCREATE INDEX \"IX_Items_FolderId\" ON \"Items\" (\"FolderId\");\n\nCREATE INDEX \"IX_Items_LogoId\" ON \"Items\" (\"LogoId\");\n\nCREATE INDEX \"IX_ItemTags_ItemId\" ON \"ItemTags\" (\"ItemId\");\n\nCREATE UNIQUE INDEX \"IX_ItemTags_ItemId_TagId\" ON \"ItemTags\" (\"ItemId\", \"TagId\");\n\nCREATE INDEX \"IX_ItemTags_TagId\" ON \"ItemTags\" (\"TagId\");\n\nCREATE UNIQUE INDEX \"IX_Logos_Source\" ON \"Logos\" (\"Source\");\n\nCREATE INDEX \"IX_Tags_Name\" ON \"Tags\" (\"Name\");\n\n\n INSERT INTO Items (Id, Name, ItemType, LogoId, FolderId, CreatedAt, UpdatedAt, IsDeleted)\n SELECT\n c.Id,\n s.Name AS Name,\n CASE\n WHEN a.Id IS NOT NULL AND (\n (a.FirstName IS NOT NULL AND a.FirstName != '') OR\n (a.LastName IS NOT NULL AND a.LastName != '') OR\n (a.Gender IS NOT NULL AND a.Gender != '') OR\n (a.BirthDate IS NOT NULL AND a.BirthDate != '' AND a.BirthDate NOT LIKE '0001-%')\n ) THEN 'Alias'\n ELSE 'Login'\n END AS ItemType,\n NULL AS LogoId,\n NULL AS FolderId,\n c.CreatedAt,\n c.UpdatedAt,\n c.IsDeleted\n FROM Credentials c\n LEFT JOIN Services s ON s.Id = c.ServiceId\n LEFT JOIN Aliases a ON a.Id = c.AliasId;\n \n\n\n INSERT INTO Logos (Id, Source, FileData, MimeType, FetchedAt, CreatedAt, UpdatedAt, IsDeleted)\n SELECT\n UPPER(SUBSTR(hex(randomblob(4)), 1, 8) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(6)), 1, 12)) AS Id,\n -- Extract and normalize hostname: remove protocol, path, lowercase, and www. prefix\n REPLACE(\n LOWER(\n SUBSTR(\n CASE\n WHEN s.Url LIKE 'https://%' THEN SUBSTR(s.Url, 9)\n WHEN s.Url LIKE 'http://%' THEN SUBSTR(s.Url, 8)\n ELSE s.Url\n END,\n 1,\n CASE\n WHEN INSTR(\n CASE\n WHEN s.Url LIKE 'https://%' THEN SUBSTR(s.Url, 9)\n WHEN s.Url LIKE 'http://%' THEN SUBSTR(s.Url, 8)\n ELSE s.Url\n END, '/') > 0\n THEN INSTR(\n CASE\n WHEN s.Url LIKE 'https://%' THEN SUBSTR(s.Url, 9)\n WHEN s.Url LIKE 'http://%' THEN SUBSTR(s.Url, 8)\n ELSE s.Url\n END, '/') - 1\n ELSE LENGTH(\n CASE\n WHEN s.Url LIKE 'https://%' THEN SUBSTR(s.Url, 9)\n WHEN s.Url LIKE 'http://%' THEN SUBSTR(s.Url, 8)\n ELSE s.Url\n END)\n END\n )\n ),\n 'www.', ''\n ) AS Source,\n s.Logo AS FileData,\n 'image/png' AS MimeType,\n NULL AS FetchedAt,\n MIN(s.CreatedAt) AS CreatedAt,\n MAX(s.UpdatedAt) AS UpdatedAt,\n 0 AS IsDeleted\n FROM Services s\n WHERE s.Logo IS NOT NULL AND s.Url IS NOT NULL AND s.Url != ''\n GROUP BY REPLACE(\n LOWER(\n SUBSTR(\n CASE\n WHEN s.Url LIKE 'https://%' THEN SUBSTR(s.Url, 9)\n WHEN s.Url LIKE 'http://%' THEN SUBSTR(s.Url, 8)\n ELSE s.Url\n END,\n 1,\n CASE\n WHEN INSTR(\n CASE\n WHEN s.Url LIKE 'https://%' THEN SUBSTR(s.Url, 9)\n WHEN s.Url LIKE 'http://%' THEN SUBSTR(s.Url, 8)\n ELSE s.Url\n END, '/') > 0\n THEN INSTR(\n CASE\n WHEN s.Url LIKE 'https://%' THEN SUBSTR(s.Url, 9)\n WHEN s.Url LIKE 'http://%' THEN SUBSTR(s.Url, 8)\n ELSE s.Url\n END, '/') - 1\n ELSE LENGTH(\n CASE\n WHEN s.Url LIKE 'https://%' THEN SUBSTR(s.Url, 9)\n WHEN s.Url LIKE 'http://%' THEN SUBSTR(s.Url, 8)\n ELSE s.Url\n END)\n END\n )\n ),\n 'www.', ''\n );\n \n\n\n UPDATE Items\n SET LogoId = (\n SELECT l.Id FROM Logos l\n INNER JOIN Services s ON REPLACE(\n LOWER(\n SUBSTR(\n CASE\n WHEN s.Url LIKE 'https://%' THEN SUBSTR(s.Url, 9)\n WHEN s.Url LIKE 'http://%' THEN SUBSTR(s.Url, 8)\n ELSE s.Url\n END,\n 1,\n CASE\n WHEN INSTR(\n CASE\n WHEN s.Url LIKE 'https://%' THEN SUBSTR(s.Url, 9)\n WHEN s.Url LIKE 'http://%' THEN SUBSTR(s.Url, 8)\n ELSE s.Url\n END, '/') > 0\n THEN INSTR(\n CASE\n WHEN s.Url LIKE 'https://%' THEN SUBSTR(s.Url, 9)\n WHEN s.Url LIKE 'http://%' THEN SUBSTR(s.Url, 8)\n ELSE s.Url\n END, '/') - 1\n ELSE LENGTH(\n CASE\n WHEN s.Url LIKE 'https://%' THEN SUBSTR(s.Url, 9)\n WHEN s.Url LIKE 'http://%' THEN SUBSTR(s.Url, 8)\n ELSE s.Url\n END)\n END\n )\n ),\n 'www.', ''\n ) = l.Source\n INNER JOIN Credentials c ON c.ServiceId = s.Id\n WHERE c.Id = Items.Id\n LIMIT 1\n )\n WHERE EXISTS (\n SELECT 1 FROM Credentials c\n INNER JOIN Services s ON s.Id = c.ServiceId\n WHERE c.Id = Items.Id AND s.Logo IS NOT NULL\n );\n \n\n\n INSERT INTO FieldValues (Id, ItemId, FieldDefinitionId, FieldKey, Value, Weight, CreatedAt, UpdatedAt, IsDeleted)\n SELECT\n UPPER(SUBSTR(hex(randomblob(4)), 1, 8) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(6)), 1, 12)) AS Id,\n c.Id AS ItemId,\n NULL AS FieldDefinitionId,\n 'login.url' AS FieldKey,\n s.Url AS Value,\n 0 AS Weight,\n s.UpdatedAt AS CreatedAt,\n s.UpdatedAt AS UpdatedAt,\n 0 AS IsDeleted\n FROM Credentials c\n INNER JOIN Services s ON s.Id = c.ServiceId\n WHERE s.Url IS NOT NULL AND s.Url != '';\n \n\n\n INSERT INTO FieldValues (Id, ItemId, FieldDefinitionId, FieldKey, Value, Weight, CreatedAt, UpdatedAt, IsDeleted)\n SELECT\n UPPER(SUBSTR(hex(randomblob(4)), 1, 8) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(6)), 1, 12)) AS Id,\n c.Id AS ItemId,\n NULL AS FieldDefinitionId,\n 'login.username' AS FieldKey,\n c.Username AS Value,\n 0 AS Weight,\n c.UpdatedAt AS CreatedAt,\n c.UpdatedAt AS UpdatedAt,\n 0 AS IsDeleted\n FROM Credentials c\n WHERE c.Username IS NOT NULL AND c.Username != '';\n \n\n\n INSERT INTO FieldValues (Id, ItemId, FieldDefinitionId, FieldKey, Value, Weight, CreatedAt, UpdatedAt, IsDeleted)\n SELECT\n UPPER(SUBSTR(hex(randomblob(4)), 1, 8) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(6)), 1, 12)) AS Id,\n c.Id AS ItemId,\n NULL AS FieldDefinitionId,\n 'login.notes' AS FieldKey,\n c.Notes AS Value,\n 0 AS Weight,\n c.UpdatedAt AS CreatedAt,\n c.UpdatedAt AS UpdatedAt,\n 0 AS IsDeleted\n FROM Credentials c\n WHERE c.Notes IS NOT NULL AND c.Notes != '';\n \n\n\n INSERT INTO FieldValues (Id, ItemId, FieldDefinitionId, FieldKey, Value, Weight, CreatedAt, UpdatedAt, IsDeleted)\n SELECT\n UPPER(SUBSTR(hex(randomblob(4)), 1, 8) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(6)), 1, 12)) AS Id,\n p.CredentialId AS ItemId,\n NULL AS FieldDefinitionId,\n 'login.password' AS FieldKey,\n p.Value AS Value,\n 0 AS Weight,\n p.UpdatedAt AS CreatedAt,\n p.UpdatedAt AS UpdatedAt,\n 0 AS IsDeleted\n FROM Passwords p\n INNER JOIN (\n SELECT CredentialId, MAX(UpdatedAt) AS MaxUpdated, MAX(Id) AS MaxId\n FROM Passwords\n WHERE IsDeleted = 0\n GROUP BY CredentialId\n ) pm ON p.CredentialId = pm.CredentialId AND p.UpdatedAt = pm.MaxUpdated AND p.Id = pm.MaxId\n WHERE p.IsDeleted = 0;\n \n\n\n INSERT INTO FieldValues (Id, ItemId, FieldDefinitionId, FieldKey, Value, Weight, CreatedAt, UpdatedAt, IsDeleted)\n SELECT\n UPPER(SUBSTR(hex(randomblob(4)), 1, 8) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(6)), 1, 12)) AS Id,\n c.Id AS ItemId,\n NULL AS FieldDefinitionId,\n 'login.email' AS FieldKey,\n a.Email AS Value,\n 0 AS Weight,\n a.UpdatedAt AS CreatedAt,\n a.UpdatedAt AS UpdatedAt,\n 0 AS IsDeleted\n FROM Credentials c\n INNER JOIN Aliases a ON a.Id = c.AliasId\n WHERE a.Email IS NOT NULL AND a.Email != '';\n \n\n\n INSERT INTO FieldValues (Id, ItemId, FieldDefinitionId, FieldKey, Value, Weight, CreatedAt, UpdatedAt, IsDeleted)\n SELECT\n UPPER(SUBSTR(hex(randomblob(4)), 1, 8) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(6)), 1, 12)) AS Id,\n c.Id AS ItemId,\n NULL AS FieldDefinitionId,\n 'alias.first_name' AS FieldKey,\n a.FirstName AS Value,\n 0 AS Weight,\n a.UpdatedAt AS CreatedAt,\n a.UpdatedAt AS UpdatedAt,\n 0 AS IsDeleted\n FROM Credentials c\n INNER JOIN Aliases a ON a.Id = c.AliasId\n WHERE a.FirstName IS NOT NULL AND a.FirstName != '';\n \n\n\n INSERT INTO FieldValues (Id, ItemId, FieldDefinitionId, FieldKey, Value, Weight, CreatedAt, UpdatedAt, IsDeleted)\n SELECT\n UPPER(SUBSTR(hex(randomblob(4)), 1, 8) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(6)), 1, 12)) AS Id,\n c.Id AS ItemId,\n NULL AS FieldDefinitionId,\n 'alias.last_name' AS FieldKey,\n a.LastName AS Value,\n 0 AS Weight,\n a.UpdatedAt AS CreatedAt,\n a.UpdatedAt AS UpdatedAt,\n 0 AS IsDeleted\n FROM Credentials c\n INNER JOIN Aliases a ON a.Id = c.AliasId\n WHERE a.LastName IS NOT NULL AND a.LastName != '';\n \n\n\n INSERT INTO FieldValues (Id, ItemId, FieldDefinitionId, FieldKey, Value, Weight, CreatedAt, UpdatedAt, IsDeleted)\n SELECT\n UPPER(SUBSTR(hex(randomblob(4)), 1, 8) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(6)), 1, 12)) AS Id,\n c.Id AS ItemId,\n NULL AS FieldDefinitionId,\n 'alias.gender' AS FieldKey,\n a.Gender AS Value,\n 0 AS Weight,\n a.UpdatedAt AS CreatedAt,\n a.UpdatedAt AS UpdatedAt,\n 0 AS IsDeleted\n FROM Credentials c\n INNER JOIN Aliases a ON a.Id = c.AliasId\n WHERE a.Gender IS NOT NULL AND a.Gender != '';\n \n\n\n INSERT INTO FieldValues (Id, ItemId, FieldDefinitionId, FieldKey, Value, Weight, CreatedAt, UpdatedAt, IsDeleted)\n SELECT\n UPPER(SUBSTR(hex(randomblob(4)), 1, 8) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(6)), 1, 12)) AS Id,\n c.Id AS ItemId,\n NULL AS FieldDefinitionId,\n 'alias.birthdate' AS FieldKey,\n SUBSTR(a.BirthDate, 1, 10) AS Value,\n 0 AS Weight,\n a.UpdatedAt AS CreatedAt,\n a.UpdatedAt AS UpdatedAt,\n 0 AS IsDeleted\n FROM Credentials c\n INNER JOIN Aliases a ON a.Id = c.AliasId\n WHERE a.BirthDate IS NOT NULL AND a.BirthDate != '' AND a.BirthDate NOT LIKE '0001-%';\n \n\nDROP TABLE \"Passwords\";\n\nDROP TABLE \"Credentials\";\n\nDROP TABLE \"Aliases\";\n\nDROP TABLE \"Services\";\n\nCREATE TABLE \"ef_temp_Attachments\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_Attachments\" PRIMARY KEY,\n \"Blob\" BLOB NOT NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"Filename\" TEXT NOT NULL,\n \"IsDeleted\" INTEGER NOT NULL,\n \"ItemId\" TEXT NOT NULL,\n \"UpdatedAt\" TEXT NOT NULL,\n CONSTRAINT \"FK_Attachments_Items_ItemId\" FOREIGN KEY (\"ItemId\") REFERENCES \"Items\" (\"Id\") ON DELETE CASCADE\n);\n\nINSERT INTO \"ef_temp_Attachments\" (\"Id\", \"Blob\", \"CreatedAt\", \"Filename\", \"IsDeleted\", \"ItemId\", \"UpdatedAt\")\nSELECT \"Id\", \"Blob\", \"CreatedAt\", \"Filename\", \"IsDeleted\", \"ItemId\", \"UpdatedAt\"\nFROM \"Attachments\";\n\nCREATE TABLE \"ef_temp_Passkeys\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_Passkeys\" PRIMARY KEY,\n \"AdditionalData\" BLOB NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"DisplayName\" TEXT NOT NULL,\n \"IsDeleted\" INTEGER NOT NULL,\n \"ItemId\" TEXT NOT NULL,\n \"PrfKey\" BLOB NULL,\n \"PrivateKey\" TEXT NOT NULL,\n \"PublicKey\" TEXT NOT NULL,\n \"RpId\" TEXT COLLATE NOCASE NOT NULL,\n \"UpdatedAt\" TEXT NOT NULL,\n \"UserHandle\" BLOB NOT NULL,\n CONSTRAINT \"FK_Passkeys_Items_ItemId\" FOREIGN KEY (\"ItemId\") REFERENCES \"Items\" (\"Id\") ON DELETE CASCADE\n);\n\nINSERT INTO \"ef_temp_Passkeys\" (\"Id\", \"AdditionalData\", \"CreatedAt\", \"DisplayName\", \"IsDeleted\", \"ItemId\", \"PrfKey\", \"PrivateKey\", \"PublicKey\", \"RpId\", \"UpdatedAt\", \"UserHandle\")\nSELECT \"Id\", \"AdditionalData\", \"CreatedAt\", \"DisplayName\", \"IsDeleted\", \"ItemId\", \"PrfKey\", \"PrivateKey\", \"PublicKey\", \"RpId\", \"UpdatedAt\", \"UserHandle\"\nFROM \"Passkeys\";\n\nCREATE TABLE \"ef_temp_TotpCodes\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_TotpCodes\" PRIMARY KEY,\n \"CreatedAt\" TEXT NOT NULL,\n \"IsDeleted\" INTEGER NOT NULL,\n \"ItemId\" TEXT NOT NULL,\n \"Name\" TEXT NOT NULL,\n \"SecretKey\" TEXT NOT NULL,\n \"UpdatedAt\" TEXT NOT NULL,\n CONSTRAINT \"FK_TotpCodes_Items_ItemId\" FOREIGN KEY (\"ItemId\") REFERENCES \"Items\" (\"Id\") ON DELETE CASCADE\n);\n\nINSERT INTO \"ef_temp_TotpCodes\" (\"Id\", \"CreatedAt\", \"IsDeleted\", \"ItemId\", \"Name\", \"SecretKey\", \"UpdatedAt\")\nSELECT \"Id\", \"CreatedAt\", \"IsDeleted\", \"ItemId\", \"Name\", \"SecretKey\", \"UpdatedAt\"\nFROM \"TotpCodes\";\n\nCOMMIT;\n\nPRAGMA foreign_keys = 0;\n\nBEGIN TRANSACTION;\nDROP TABLE \"Attachments\";\n\nALTER TABLE \"ef_temp_Attachments\" RENAME TO \"Attachments\";\n\nDROP TABLE \"Passkeys\";\n\nALTER TABLE \"ef_temp_Passkeys\" RENAME TO \"Passkeys\";\n\nDROP TABLE \"TotpCodes\";\n\nALTER TABLE \"ef_temp_TotpCodes\" RENAME TO \"TotpCodes\";\n\nCOMMIT;\n\nPRAGMA foreign_keys = 1;\n\nBEGIN TRANSACTION;\nCREATE INDEX \"IX_Attachments_ItemId\" ON \"Attachments\" (\"ItemId\");\n\nCREATE INDEX \"IX_Passkeys_ItemId\" ON \"Passkeys\" (\"ItemId\");\n\nCREATE INDEX \"IX_Passkeys_RpId\" ON \"Passkeys\" (\"RpId\");\n\nCREATE INDEX \"IX_TotpCodes_ItemId\" ON \"TotpCodes\" (\"ItemId\");\n\nCOMMIT;\n\nINSERT INTO \"__EFMigrationsHistory\" (\"MigrationId\", \"ProductVersion\")\nVALUES ('20251213111207_1.7.0-FieldBasedDataModelUpdate', '9.0.4');\n"; +declare const COMPLETE_SCHEMA_SQL = "\n\uFEFFCREATE TABLE IF NOT EXISTS \"__EFMigrationsHistory\" (\n \"MigrationId\" TEXT NOT NULL CONSTRAINT \"PK___EFMigrationsHistory\" PRIMARY KEY,\n \"ProductVersion\" TEXT NOT NULL\n);\n\nBEGIN TRANSACTION;\nCREATE TABLE \"Aliases\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_Aliases\" PRIMARY KEY,\n \"Gender\" VARCHAR NULL,\n \"FirstName\" VARCHAR NULL,\n \"LastName\" VARCHAR NULL,\n \"NickName\" VARCHAR NULL,\n \"BirthDate\" TEXT NOT NULL,\n \"AddressStreet\" VARCHAR NULL,\n \"AddressCity\" VARCHAR NULL,\n \"AddressState\" VARCHAR NULL,\n \"AddressZipCode\" VARCHAR NULL,\n \"AddressCountry\" VARCHAR NULL,\n \"Hobbies\" TEXT NULL,\n \"EmailPrefix\" TEXT NULL,\n \"PhoneMobile\" TEXT NULL,\n \"BankAccountIBAN\" TEXT NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"UpdatedAt\" TEXT NOT NULL\n);\n\nCREATE TABLE \"Services\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_Services\" PRIMARY KEY,\n \"Name\" TEXT NULL,\n \"Url\" TEXT NULL,\n \"Logo\" BLOB NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"UpdatedAt\" TEXT NOT NULL\n);\n\nCREATE TABLE \"Credentials\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_Credentials\" PRIMARY KEY,\n \"AliasId\" TEXT NOT NULL,\n \"Notes\" TEXT NULL,\n \"Username\" TEXT NOT NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"UpdatedAt\" TEXT NOT NULL,\n \"ServiceId\" TEXT NOT NULL,\n CONSTRAINT \"FK_Credentials_Aliases_AliasId\" FOREIGN KEY (\"AliasId\") REFERENCES \"Aliases\" (\"Id\") ON DELETE CASCADE,\n CONSTRAINT \"FK_Credentials_Services_ServiceId\" FOREIGN KEY (\"ServiceId\") REFERENCES \"Services\" (\"Id\") ON DELETE CASCADE\n);\n\nCREATE TABLE \"Attachment\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_Attachment\" PRIMARY KEY,\n \"Filename\" TEXT NOT NULL,\n \"Blob\" BLOB NOT NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"UpdatedAt\" TEXT NOT NULL,\n \"CredentialId\" TEXT NOT NULL,\n CONSTRAINT \"FK_Attachment_Credentials_CredentialId\" FOREIGN KEY (\"CredentialId\") REFERENCES \"Credentials\" (\"Id\") ON DELETE CASCADE\n);\n\nCREATE TABLE \"Passwords\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_Passwords\" PRIMARY KEY,\n \"Value\" TEXT NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"UpdatedAt\" TEXT NOT NULL,\n \"CredentialId\" TEXT NOT NULL,\n CONSTRAINT \"FK_Passwords_Credentials_CredentialId\" FOREIGN KEY (\"CredentialId\") REFERENCES \"Credentials\" (\"Id\") ON DELETE CASCADE\n);\n\nCREATE INDEX \"IX_Attachment_CredentialId\" ON \"Attachment\" (\"CredentialId\");\n\nCREATE INDEX \"IX_Credentials_AliasId\" ON \"Credentials\" (\"AliasId\");\n\nCREATE INDEX \"IX_Credentials_ServiceId\" ON \"Credentials\" (\"ServiceId\");\n\nCREATE INDEX \"IX_Passwords_CredentialId\" ON \"Passwords\" (\"CredentialId\");\n\nINSERT INTO \"__EFMigrationsHistory\" (\"MigrationId\", \"ProductVersion\")\nVALUES ('20240708094944_1.0.0-InitialMigration', '9.0.4');\n\nINSERT INTO \"__EFMigrationsHistory\" (\"MigrationId\", \"ProductVersion\")\nVALUES ('20240708224522_1.0.1-EmptyTestMigration', '9.0.4');\n\nALTER TABLE \"Aliases\" RENAME COLUMN \"EmailPrefix\" TO \"Email\";\n\nINSERT INTO \"__EFMigrationsHistory\" (\"MigrationId\", \"ProductVersion\")\nVALUES ('20240711204207_1.0.2-ChangeEmailColumn', '9.0.4');\n\nCREATE TABLE \"EncryptionKeys\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_EncryptionKeys\" PRIMARY KEY,\n \"PublicKey\" TEXT NOT NULL,\n \"PrivateKey\" TEXT NOT NULL,\n \"IsPrimary\" INTEGER NOT NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"UpdatedAt\" TEXT NOT NULL\n);\n\nINSERT INTO \"__EFMigrationsHistory\" (\"MigrationId\", \"ProductVersion\")\nVALUES ('20240729105618_1.1.0-AddPkiTables', '9.0.4');\n\nCREATE TABLE \"Settings\" (\n \"Key\" TEXT NOT NULL CONSTRAINT \"PK_Settings\" PRIMARY KEY,\n \"Value\" TEXT NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"UpdatedAt\" TEXT NOT NULL\n);\n\nINSERT INTO \"__EFMigrationsHistory\" (\"MigrationId\", \"ProductVersion\")\nVALUES ('20240805073413_1.2.0-AddSettingsTable', '9.0.4');\n\nCREATE TABLE \"ef_temp_Aliases\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_Aliases\" PRIMARY KEY,\n \"BirthDate\" TEXT NOT NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"Email\" TEXT NULL,\n \"FirstName\" VARCHAR NULL,\n \"Gender\" VARCHAR NULL,\n \"LastName\" VARCHAR NULL,\n \"NickName\" VARCHAR NULL,\n \"UpdatedAt\" TEXT NOT NULL\n);\n\nINSERT INTO \"ef_temp_Aliases\" (\"Id\", \"BirthDate\", \"CreatedAt\", \"Email\", \"FirstName\", \"Gender\", \"LastName\", \"NickName\", \"UpdatedAt\")\nSELECT \"Id\", \"BirthDate\", \"CreatedAt\", \"Email\", \"FirstName\", \"Gender\", \"LastName\", \"NickName\", \"UpdatedAt\"\nFROM \"Aliases\";\n\nCOMMIT;\n\nPRAGMA foreign_keys = 0;\n\nBEGIN TRANSACTION;\nDROP TABLE \"Aliases\";\n\nALTER TABLE \"ef_temp_Aliases\" RENAME TO \"Aliases\";\n\nCOMMIT;\n\nPRAGMA foreign_keys = 1;\n\nINSERT INTO \"__EFMigrationsHistory\" (\"MigrationId\", \"ProductVersion\")\nVALUES ('20240805122422_1.3.0-UpdateIdentityStructure', '9.0.4');\n\nBEGIN TRANSACTION;\nCREATE TABLE \"ef_temp_Credentials\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_Credentials\" PRIMARY KEY,\n \"AliasId\" TEXT NOT NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"Notes\" TEXT NULL,\n \"ServiceId\" TEXT NOT NULL,\n \"UpdatedAt\" TEXT NOT NULL,\n \"Username\" TEXT NULL,\n CONSTRAINT \"FK_Credentials_Aliases_AliasId\" FOREIGN KEY (\"AliasId\") REFERENCES \"Aliases\" (\"Id\") ON DELETE CASCADE,\n CONSTRAINT \"FK_Credentials_Services_ServiceId\" FOREIGN KEY (\"ServiceId\") REFERENCES \"Services\" (\"Id\") ON DELETE CASCADE\n);\n\nINSERT INTO \"ef_temp_Credentials\" (\"Id\", \"AliasId\", \"CreatedAt\", \"Notes\", \"ServiceId\", \"UpdatedAt\", \"Username\")\nSELECT \"Id\", \"AliasId\", \"CreatedAt\", \"Notes\", \"ServiceId\", \"UpdatedAt\", \"Username\"\nFROM \"Credentials\";\n\nCOMMIT;\n\nPRAGMA foreign_keys = 0;\n\nBEGIN TRANSACTION;\nDROP TABLE \"Credentials\";\n\nALTER TABLE \"ef_temp_Credentials\" RENAME TO \"Credentials\";\n\nCOMMIT;\n\nPRAGMA foreign_keys = 1;\n\nBEGIN TRANSACTION;\nCREATE INDEX \"IX_Credentials_AliasId\" ON \"Credentials\" (\"AliasId\");\n\nCREATE INDEX \"IX_Credentials_ServiceId\" ON \"Credentials\" (\"ServiceId\");\n\nCOMMIT;\n\nINSERT INTO \"__EFMigrationsHistory\" (\"MigrationId\", \"ProductVersion\")\nVALUES ('20240812141727_1.3.1-MakeUsernameOptional', '9.0.4');\n\nBEGIN TRANSACTION;\nALTER TABLE \"Settings\" ADD \"IsDeleted\" INTEGER NOT NULL DEFAULT 0;\n\nALTER TABLE \"Services\" ADD \"IsDeleted\" INTEGER NOT NULL DEFAULT 0;\n\nALTER TABLE \"Passwords\" ADD \"IsDeleted\" INTEGER NOT NULL DEFAULT 0;\n\nALTER TABLE \"EncryptionKeys\" ADD \"IsDeleted\" INTEGER NOT NULL DEFAULT 0;\n\nALTER TABLE \"Credentials\" ADD \"IsDeleted\" INTEGER NOT NULL DEFAULT 0;\n\nALTER TABLE \"Attachment\" ADD \"IsDeleted\" INTEGER NOT NULL DEFAULT 0;\n\nALTER TABLE \"Aliases\" ADD \"IsDeleted\" INTEGER NOT NULL DEFAULT 0;\n\nINSERT INTO \"__EFMigrationsHistory\" (\"MigrationId\", \"ProductVersion\")\nVALUES ('20240916105320_1.4.0-AddSyncSupport', '9.0.4');\n\nALTER TABLE \"Attachment\" RENAME TO \"Attachments\";\n\nCREATE TABLE \"ef_temp_Attachments\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_Attachments\" PRIMARY KEY,\n \"Blob\" BLOB NOT NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"CredentialId\" TEXT NOT NULL,\n \"Filename\" TEXT NOT NULL,\n \"IsDeleted\" INTEGER NOT NULL,\n \"UpdatedAt\" TEXT NOT NULL,\n CONSTRAINT \"FK_Attachments_Credentials_CredentialId\" FOREIGN KEY (\"CredentialId\") REFERENCES \"Credentials\" (\"Id\") ON DELETE CASCADE\n);\n\nINSERT INTO \"ef_temp_Attachments\" (\"Id\", \"Blob\", \"CreatedAt\", \"CredentialId\", \"Filename\", \"IsDeleted\", \"UpdatedAt\")\nSELECT \"Id\", \"Blob\", \"CreatedAt\", \"CredentialId\", \"Filename\", \"IsDeleted\", \"UpdatedAt\"\nFROM \"Attachments\";\n\nCOMMIT;\n\nPRAGMA foreign_keys = 0;\n\nBEGIN TRANSACTION;\nDROP TABLE \"Attachments\";\n\nALTER TABLE \"ef_temp_Attachments\" RENAME TO \"Attachments\";\n\nCOMMIT;\n\nPRAGMA foreign_keys = 1;\n\nBEGIN TRANSACTION;\nCREATE INDEX \"IX_Attachments_CredentialId\" ON \"Attachments\" (\"CredentialId\");\n\nCOMMIT;\n\nINSERT INTO \"__EFMigrationsHistory\" (\"MigrationId\", \"ProductVersion\")\nVALUES ('20240917191243_1.4.1-RenameAttachmentsPlural', '9.0.4');\n\nBEGIN TRANSACTION;\nCREATE TABLE \"TotpCodes\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_TotpCodes\" PRIMARY KEY,\n \"Name\" TEXT NOT NULL,\n \"SecretKey\" TEXT NOT NULL,\n \"CredentialId\" TEXT NOT NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"UpdatedAt\" TEXT NOT NULL,\n \"IsDeleted\" INTEGER NOT NULL,\n CONSTRAINT \"FK_TotpCodes_Credentials_CredentialId\" FOREIGN KEY (\"CredentialId\") REFERENCES \"Credentials\" (\"Id\") ON DELETE CASCADE\n);\n\nCREATE INDEX \"IX_TotpCodes_CredentialId\" ON \"TotpCodes\" (\"CredentialId\");\n\nINSERT INTO \"__EFMigrationsHistory\" (\"MigrationId\", \"ProductVersion\")\nVALUES ('20250310131554_1.5.0-AddTotpCodes', '9.0.4');\n\n\nPRAGMA foreign_keys = OFF;\n\n-- Clean up any existing temp tables first\nDROP TABLE IF EXISTS \"__EFMigrationsHistory_temp\";\nDROP TABLE IF EXISTS \"Aliases_temp\";\nDROP TABLE IF EXISTS \"Services_temp\";\nDROP TABLE IF EXISTS \"EncryptionKeys_temp\";\nDROP TABLE IF EXISTS \"Settings_temp\";\nDROP TABLE IF EXISTS \"Credentials_temp\";\nDROP TABLE IF EXISTS \"Attachments_temp\";\nDROP TABLE IF EXISTS \"Passwords_temp\";\nDROP TABLE IF EXISTS \"TotpCodes_temp\";\n\n-- Create backup tables for all data\nCREATE TABLE \"__EFMigrationsHistory_temp\" AS SELECT * FROM \"__EFMigrationsHistory\";\nCREATE TABLE \"Aliases_temp\" AS SELECT * FROM \"Aliases\";\nCREATE TABLE \"Services_temp\" AS SELECT * FROM \"Services\";\nCREATE TABLE \"EncryptionKeys_temp\" AS SELECT * FROM \"EncryptionKeys\";\nCREATE TABLE \"Settings_temp\" AS SELECT * FROM \"Settings\";\nCREATE TABLE \"Credentials_temp\" AS SELECT * FROM \"Credentials\";\nCREATE TABLE \"Attachments_temp\" AS SELECT * FROM \"Attachments\";\nCREATE TABLE \"Passwords_temp\" AS SELECT * FROM \"Passwords\";\nCREATE TABLE \"TotpCodes_temp\" AS SELECT * FROM \"TotpCodes\";\n\n-- Delete orphaned records that do not have a valid FK to the credential object\nDELETE FROM \"Attachments_temp\" WHERE \"CredentialId\" NOT IN (SELECT \"Id\" FROM \"Credentials_temp\");\nDELETE FROM \"Passwords_temp\" WHERE \"CredentialId\" NOT IN (SELECT \"Id\" FROM \"Credentials_temp\");\nDELETE FROM \"TotpCodes_temp\" WHERE \"CredentialId\" NOT IN (SELECT \"Id\" FROM \"Credentials_temp\");\n\n-- Delete orphaned credentials that do not have valid FKs to alias or service objects\nDELETE FROM \"Credentials_temp\" WHERE \"AliasId\" NOT IN (SELECT \"Id\" FROM \"Aliases_temp\");\nDELETE FROM \"Credentials_temp\" WHERE \"ServiceId\" NOT IN (SELECT \"Id\" FROM \"Services_temp\");\n\n-- After cleaning credentials, clean dependent tables again in case we removed credentials\nDELETE FROM \"Attachments_temp\" WHERE \"CredentialId\" NOT IN (SELECT \"Id\" FROM \"Credentials_temp\");\nDELETE FROM \"Passwords_temp\" WHERE \"CredentialId\" NOT IN (SELECT \"Id\" FROM \"Credentials_temp\");\nDELETE FROM \"TotpCodes_temp\" WHERE \"CredentialId\" NOT IN (SELECT \"Id\" FROM \"Credentials_temp\");\n\n-- Drop all existing tables\nDROP TABLE \"TotpCodes\";\nDROP TABLE \"Passwords\";\nDROP TABLE \"Attachments\";\nDROP TABLE \"Credentials\";\nDROP TABLE \"Settings\";\nDROP TABLE \"EncryptionKeys\";\nDROP TABLE \"Services\";\nDROP TABLE \"Aliases\";\nDROP TABLE \"__EFMigrationsHistory\";\n\n-- Recreate tables with proper constraints (no dependencies first)\nCREATE TABLE \"__EFMigrationsHistory\" (\n \"MigrationId\" TEXT NOT NULL CONSTRAINT \"PK___EFMigrationsHistory\" PRIMARY KEY,\n \"ProductVersion\" TEXT NOT NULL\n);\n\nCREATE TABLE \"Aliases\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_Aliases\" PRIMARY KEY,\n \"BirthDate\" TEXT NOT NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"Email\" TEXT NULL,\n \"FirstName\" VARCHAR NULL,\n \"Gender\" VARCHAR NULL,\n \"LastName\" VARCHAR NULL,\n \"NickName\" VARCHAR NULL,\n \"UpdatedAt\" TEXT NOT NULL,\n \"IsDeleted\" INTEGER NOT NULL DEFAULT 0\n);\n\nCREATE TABLE \"Services\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_Services\" PRIMARY KEY,\n \"Name\" TEXT NULL,\n \"Url\" TEXT NULL,\n \"Logo\" BLOB NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"UpdatedAt\" TEXT NOT NULL,\n \"IsDeleted\" INTEGER NOT NULL DEFAULT 0\n);\n\nCREATE TABLE \"EncryptionKeys\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_EncryptionKeys\" PRIMARY KEY,\n \"PublicKey\" TEXT NOT NULL,\n \"PrivateKey\" TEXT NOT NULL,\n \"IsPrimary\" INTEGER NOT NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"UpdatedAt\" TEXT NOT NULL,\n \"IsDeleted\" INTEGER NOT NULL DEFAULT 0\n);\n\nCREATE TABLE \"Settings\" (\n \"Key\" TEXT NOT NULL CONSTRAINT \"PK_Settings\" PRIMARY KEY,\n \"Value\" TEXT NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"UpdatedAt\" TEXT NOT NULL,\n \"IsDeleted\" INTEGER NOT NULL DEFAULT 0\n);\n\n-- Tables with foreign keys\nCREATE TABLE \"Credentials\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_Credentials\" PRIMARY KEY,\n \"AliasId\" TEXT NOT NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"Notes\" TEXT NULL,\n \"ServiceId\" TEXT NOT NULL,\n \"UpdatedAt\" TEXT NOT NULL,\n \"Username\" TEXT NULL,\n \"IsDeleted\" INTEGER NOT NULL DEFAULT 0,\n CONSTRAINT \"FK_Credentials_Aliases_AliasId\" FOREIGN KEY (\"AliasId\") REFERENCES \"Aliases\" (\"Id\") ON DELETE CASCADE,\n CONSTRAINT \"FK_Credentials_Services_ServiceId\" FOREIGN KEY (\"ServiceId\") REFERENCES \"Services\" (\"Id\") ON DELETE CASCADE\n);\n\nCREATE TABLE \"Attachments\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_Attachments\" PRIMARY KEY,\n \"Blob\" BLOB NOT NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"CredentialId\" TEXT NOT NULL,\n \"Filename\" TEXT NOT NULL,\n \"IsDeleted\" INTEGER NOT NULL DEFAULT 0,\n \"UpdatedAt\" TEXT NOT NULL,\n CONSTRAINT \"FK_Attachments_Credentials_CredentialId\" FOREIGN KEY (\"CredentialId\") REFERENCES \"Credentials\" (\"Id\") ON DELETE CASCADE\n);\n\nCREATE TABLE \"Passwords\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_Passwords\" PRIMARY KEY,\n \"Value\" TEXT NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"UpdatedAt\" TEXT NOT NULL,\n \"CredentialId\" TEXT NOT NULL,\n \"IsDeleted\" INTEGER NOT NULL DEFAULT 0,\n CONSTRAINT \"FK_Passwords_Credentials_CredentialId\" FOREIGN KEY (\"CredentialId\") REFERENCES \"Credentials\" (\"Id\") ON DELETE CASCADE\n);\n\nCREATE TABLE \"TotpCodes\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_TotpCodes\" PRIMARY KEY,\n \"Name\" TEXT NOT NULL,\n \"SecretKey\" TEXT NOT NULL,\n \"CredentialId\" TEXT NOT NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"UpdatedAt\" TEXT NOT NULL,\n \"IsDeleted\" INTEGER NOT NULL DEFAULT 0,\n CONSTRAINT \"FK_TotpCodes_Credentials_CredentialId\" FOREIGN KEY (\"CredentialId\") REFERENCES \"Credentials\" (\"Id\") ON DELETE CASCADE\n);\n\n\n-- Restore data from temp tables\nINSERT INTO \"__EFMigrationsHistory\" SELECT * FROM \"__EFMigrationsHistory_temp\";\nINSERT INTO \"Aliases\" SELECT * FROM \"Aliases_temp\";\nINSERT INTO \"Services\" SELECT * FROM \"Services_temp\";\nINSERT INTO \"EncryptionKeys\" SELECT * FROM \"EncryptionKeys_temp\";\nINSERT INTO \"Settings\" SELECT * FROM \"Settings_temp\";\nINSERT INTO \"Credentials\" SELECT * FROM \"Credentials_temp\";\nINSERT INTO \"Attachments\" SELECT * FROM \"Attachments_temp\";\nINSERT INTO \"Passwords\" SELECT * FROM \"Passwords_temp\";\nINSERT INTO \"TotpCodes\" SELECT * FROM \"TotpCodes_temp\";\n\n-- =====================================================================================\n-- Date Format Normalization Migration\n-- =====================================================================================\n-- This migration normalizes ALL date fields to the standard format: 'yyyy-MM-dd HH:mm:ss.fff'\n-- Previously the different clients used different date formats which complicate date parsing.\n-- From version 0.24.0 onwards, all new dates are stored in this standard format.\n\n-- Update Aliases table (CreatedAt, UpdatedAt, BirthDate)\nUPDATE \"Aliases\" SET \"CreatedAt\" =\n CASE\n -- Already in correct format (yyyy-MM-dd HH:mm:ss.fff) - no change\n WHEN \"CreatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9] [0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9][0-9][0-9]'\n THEN \"CreatedAt\"\n\n -- ISO 8601 with milliseconds (yyyy-MM-ddTHH:mm:ss.fffZ) -> Replace T with space, remove Z and everything after .fff\n WHEN \"CreatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]T[0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9]*'\n THEN substr(\"CreatedAt\", 1, 10) || ' ' || substr(\"CreatedAt\", 12, 12)\n\n -- Without milliseconds (yyyy-MM-dd HH:mm:ss or yyyy-MM-ddTHH:mm:ssZ) -> Add .000\n WHEN \"CreatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9][T ][0-9][0-9]:[0-9][0-9]:[0-9][0-9]*'\n THEN substr(\"CreatedAt\", 1, 10) || ' ' || substr(replace(\"CreatedAt\", 'T', ' '), 12, 8) || '.000'\n\n -- Fallback: if none match, keep as-is (edge case)\n ELSE \"CreatedAt\"\n END;\n\nUPDATE \"Aliases\" SET \"UpdatedAt\" =\n CASE\n WHEN \"UpdatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9] [0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9][0-9][0-9]'\n THEN \"UpdatedAt\"\n WHEN \"UpdatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]T[0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9]*'\n THEN substr(\"UpdatedAt\", 1, 10) || ' ' || substr(\"UpdatedAt\", 12, 12)\n WHEN \"UpdatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9][T ][0-9][0-9]:[0-9][0-9]:[0-9][0-9]*'\n THEN substr(\"UpdatedAt\", 1, 10) || ' ' || substr(replace(\"UpdatedAt\", 'T', ' '), 12, 8) || '.000'\n ELSE \"UpdatedAt\"\n END;\n\n-- BirthDate: Always set time to 00:00:00 (no milliseconds for birth dates)\nUPDATE \"Aliases\" SET \"BirthDate\" =\n CASE\n -- If empty or already '0001-01-01 00:00:00', keep as-is\n WHEN \"BirthDate\" = '' OR \"BirthDate\" = '0001-01-01 00:00:00'\n THEN \"BirthDate\"\n\n -- If already in correct format (yyyy-MM-dd 00:00:00), keep as-is\n WHEN \"BirthDate\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9] 00:00:00'\n THEN \"BirthDate\"\n\n -- Extract date part and set time to 00:00:00\n WHEN \"BirthDate\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]*'\n THEN substr(\"BirthDate\", 1, 10) || ' 00:00:00'\n\n -- Fallback\n ELSE \"BirthDate\"\n END;\n\n-- Update Services table (CreatedAt, UpdatedAt)\nUPDATE \"Services\" SET \"CreatedAt\" =\n CASE\n WHEN \"CreatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9] [0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9][0-9][0-9]'\n THEN \"CreatedAt\"\n WHEN \"CreatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]T[0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9]*'\n THEN substr(\"CreatedAt\", 1, 10) || ' ' || substr(\"CreatedAt\", 12, 12)\n WHEN \"CreatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9][T ][0-9][0-9]:[0-9][0-9]:[0-9][0-9]*'\n THEN substr(\"CreatedAt\", 1, 10) || ' ' || substr(replace(\"CreatedAt\", 'T', ' '), 12, 8) || '.000'\n ELSE \"CreatedAt\"\n END;\n\nUPDATE \"Services\" SET \"UpdatedAt\" =\n CASE\n WHEN \"UpdatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9] [0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9][0-9][0-9]'\n THEN \"UpdatedAt\"\n WHEN \"UpdatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]T[0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9]*'\n THEN substr(\"UpdatedAt\", 1, 10) || ' ' || substr(\"UpdatedAt\", 12, 12)\n WHEN \"UpdatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9][T ][0-9][0-9]:[0-9][0-9]:[0-9][0-9]*'\n THEN substr(\"UpdatedAt\", 1, 10) || ' ' || substr(replace(\"UpdatedAt\", 'T', ' '), 12, 8) || '.000'\n ELSE \"UpdatedAt\"\n END;\n\n-- Update EncryptionKeys table (CreatedAt, UpdatedAt)\nUPDATE \"EncryptionKeys\" SET \"CreatedAt\" =\n CASE\n WHEN \"CreatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9] [0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9][0-9][0-9]'\n THEN \"CreatedAt\"\n WHEN \"CreatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]T[0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9]*'\n THEN substr(\"CreatedAt\", 1, 10) || ' ' || substr(\"CreatedAt\", 12, 12)\n WHEN \"CreatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9][T ][0-9][0-9]:[0-9][0-9]:[0-9][0-9]*'\n THEN substr(\"CreatedAt\", 1, 10) || ' ' || substr(replace(\"CreatedAt\", 'T', ' '), 12, 8) || '.000'\n ELSE \"CreatedAt\"\n END;\n\nUPDATE \"EncryptionKeys\" SET \"UpdatedAt\" =\n CASE\n WHEN \"UpdatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9] [0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9][0-9][0-9]'\n THEN \"UpdatedAt\"\n WHEN \"UpdatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]T[0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9]*'\n THEN substr(\"UpdatedAt\", 1, 10) || ' ' || substr(\"UpdatedAt\", 12, 12)\n WHEN \"UpdatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9][T ][0-9][0-9]:[0-9][0-9]:[0-9][0-9]*'\n THEN substr(\"UpdatedAt\", 1, 10) || ' ' || substr(replace(\"UpdatedAt\", 'T', ' '), 12, 8) || '.000'\n ELSE \"UpdatedAt\"\n END;\n\n-- Update Settings table (CreatedAt, UpdatedAt)\nUPDATE \"Settings\" SET \"CreatedAt\" =\n CASE\n WHEN \"CreatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9] [0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9][0-9][0-9]'\n THEN \"CreatedAt\"\n WHEN \"CreatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]T[0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9]*'\n THEN substr(\"CreatedAt\", 1, 10) || ' ' || substr(\"CreatedAt\", 12, 12)\n WHEN \"CreatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9][T ][0-9][0-9]:[0-9][0-9]:[0-9][0-9]*'\n THEN substr(\"CreatedAt\", 1, 10) || ' ' || substr(replace(\"CreatedAt\", 'T', ' '), 12, 8) || '.000'\n ELSE \"CreatedAt\"\n END;\n\nUPDATE \"Settings\" SET \"UpdatedAt\" =\n CASE\n WHEN \"UpdatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9] [0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9][0-9][0-9]'\n THEN \"UpdatedAt\"\n WHEN \"UpdatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]T[0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9]*'\n THEN substr(\"UpdatedAt\", 1, 10) || ' ' || substr(\"UpdatedAt\", 12, 12)\n WHEN \"UpdatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9][T ][0-9][0-9]:[0-9][0-9]:[0-9][0-9]*'\n THEN substr(\"UpdatedAt\", 1, 10) || ' ' || substr(replace(\"UpdatedAt\", 'T', ' '), 12, 8) || '.000'\n ELSE \"UpdatedAt\"\n END;\n\n-- Update Credentials table (CreatedAt, UpdatedAt)\nUPDATE \"Credentials\" SET \"CreatedAt\" =\n CASE\n WHEN \"CreatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9] [0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9][0-9][0-9]'\n THEN \"CreatedAt\"\n WHEN \"CreatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]T[0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9]*'\n THEN substr(\"CreatedAt\", 1, 10) || ' ' || substr(\"CreatedAt\", 12, 12)\n WHEN \"CreatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9][T ][0-9][0-9]:[0-9][0-9]:[0-9][0-9]*'\n THEN substr(\"CreatedAt\", 1, 10) || ' ' || substr(replace(\"CreatedAt\", 'T', ' '), 12, 8) || '.000'\n ELSE \"CreatedAt\"\n END;\n\nUPDATE \"Credentials\" SET \"UpdatedAt\" =\n CASE\n WHEN \"UpdatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9] [0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9][0-9][0-9]'\n THEN \"UpdatedAt\"\n WHEN \"UpdatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]T[0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9]*'\n THEN substr(\"UpdatedAt\", 1, 10) || ' ' || substr(\"UpdatedAt\", 12, 12)\n WHEN \"UpdatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9][T ][0-9][0-9]:[0-9][0-9]:[0-9][0-9]*'\n THEN substr(\"UpdatedAt\", 1, 10) || ' ' || substr(replace(\"UpdatedAt\", 'T', ' '), 12, 8) || '.000'\n ELSE \"UpdatedAt\"\n END;\n\n-- Update Attachments table (CreatedAt, UpdatedAt)\nUPDATE \"Attachments\" SET \"CreatedAt\" =\n CASE\n WHEN \"CreatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9] [0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9][0-9][0-9]'\n THEN \"CreatedAt\"\n WHEN \"CreatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]T[0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9]*'\n THEN substr(\"CreatedAt\", 1, 10) || ' ' || substr(\"CreatedAt\", 12, 12)\n WHEN \"CreatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9][T ][0-9][0-9]:[0-9][0-9]:[0-9][0-9]*'\n THEN substr(\"CreatedAt\", 1, 10) || ' ' || substr(replace(\"CreatedAt\", 'T', ' '), 12, 8) || '.000'\n ELSE \"CreatedAt\"\n END;\n\nUPDATE \"Attachments\" SET \"UpdatedAt\" =\n CASE\n WHEN \"UpdatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9] [0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9][0-9][0-9]'\n THEN \"UpdatedAt\"\n WHEN \"UpdatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]T[0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9]*'\n THEN substr(\"UpdatedAt\", 1, 10) || ' ' || substr(\"UpdatedAt\", 12, 12)\n WHEN \"UpdatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9][T ][0-9][0-9]:[0-9][0-9]:[0-9][0-9]*'\n THEN substr(\"UpdatedAt\", 1, 10) || ' ' || substr(replace(\"UpdatedAt\", 'T', ' '), 12, 8) || '.000'\n ELSE \"UpdatedAt\"\n END;\n\n-- Update Passwords table (CreatedAt, UpdatedAt)\nUPDATE \"Passwords\" SET \"CreatedAt\" =\n CASE\n WHEN \"CreatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9] [0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9][0-9][0-9]'\n THEN \"CreatedAt\"\n WHEN \"CreatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]T[0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9]*'\n THEN substr(\"CreatedAt\", 1, 10) || ' ' || substr(\"CreatedAt\", 12, 12)\n WHEN \"CreatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9][T ][0-9][0-9]:[0-9][0-9]:[0-9][0-9]*'\n THEN substr(\"CreatedAt\", 1, 10) || ' ' || substr(replace(\"CreatedAt\", 'T', ' '), 12, 8) || '.000'\n ELSE \"CreatedAt\"\n END;\n\nUPDATE \"Passwords\" SET \"UpdatedAt\" =\n CASE\n WHEN \"UpdatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9] [0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9][0-9][0-9]'\n THEN \"UpdatedAt\"\n WHEN \"UpdatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]T[0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9]*'\n THEN substr(\"UpdatedAt\", 1, 10) || ' ' || substr(\"UpdatedAt\", 12, 12)\n WHEN \"UpdatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9][T ][0-9][0-9]:[0-9][0-9]:[0-9][0-9]*'\n THEN substr(\"UpdatedAt\", 1, 10) || ' ' || substr(replace(\"UpdatedAt\", 'T', ' '), 12, 8) || '.000'\n ELSE \"UpdatedAt\"\n END;\n\n-- Update TotpCodes table (CreatedAt, UpdatedAt)\nUPDATE \"TotpCodes\" SET \"CreatedAt\" =\n CASE\n WHEN \"CreatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9] [0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9][0-9][0-9]'\n THEN \"CreatedAt\"\n WHEN \"CreatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]T[0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9]*'\n THEN substr(\"CreatedAt\", 1, 10) || ' ' || substr(\"CreatedAt\", 12, 12)\n WHEN \"CreatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9][T ][0-9][0-9]:[0-9][0-9]:[0-9][0-9]*'\n THEN substr(\"CreatedAt\", 1, 10) || ' ' || substr(replace(\"CreatedAt\", 'T', ' '), 12, 8) || '.000'\n ELSE \"CreatedAt\"\n END;\n\nUPDATE \"TotpCodes\" SET \"UpdatedAt\" =\n CASE\n WHEN \"UpdatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9] [0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9][0-9][0-9]'\n THEN \"UpdatedAt\"\n WHEN \"UpdatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]T[0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9]*'\n THEN substr(\"UpdatedAt\", 1, 10) || ' ' || substr(\"UpdatedAt\", 12, 12)\n WHEN \"UpdatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9][T ][0-9][0-9]:[0-9][0-9]:[0-9][0-9]*'\n THEN substr(\"UpdatedAt\", 1, 10) || ' ' || substr(replace(\"UpdatedAt\", 'T', ' '), 12, 8) || '.000'\n ELSE \"UpdatedAt\"\n END;\n\n-- =====================================================================================\n-- End of Date Format Normalization Migration\n-- =====================================================================================\n\n-- Recreate indexes\nCREATE INDEX \"IX_Credentials_AliasId\" ON \"Credentials\" (\"AliasId\");\nCREATE INDEX \"IX_Credentials_ServiceId\" ON \"Credentials\" (\"ServiceId\");\nCREATE INDEX \"IX_Attachments_CredentialId\" ON \"Attachments\" (\"CredentialId\");\nCREATE INDEX \"IX_Passwords_CredentialId\" ON \"Passwords\" (\"CredentialId\");\nCREATE INDEX \"IX_TotpCodes_CredentialId\" ON \"TotpCodes\" (\"CredentialId\");\n\n-- Clean up temp tables\nDROP TABLE \"__EFMigrationsHistory_temp\";\nDROP TABLE \"Aliases_temp\";\nDROP TABLE \"Services_temp\";\nDROP TABLE \"EncryptionKeys_temp\";\nDROP TABLE \"Settings_temp\";\nDROP TABLE \"Credentials_temp\";\nDROP TABLE \"Attachments_temp\";\nDROP TABLE \"Passwords_temp\";\nDROP TABLE \"TotpCodes_temp\";\n\nPRAGMA foreign_keys = ON;\n\n\nCREATE TABLE \"Passkeys\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_Passkeys\" PRIMARY KEY,\n \"RpId\" TEXT COLLATE NOCASE NOT NULL,\n \"UserHandle\" BLOB NOT NULL,\n \"PublicKey\" TEXT NOT NULL,\n \"PrivateKey\" TEXT NOT NULL,\n \"PrfKey\" BLOB NULL,\n \"DisplayName\" TEXT NOT NULL,\n \"AdditionalData\" BLOB NULL,\n \"CredentialId\" TEXT NOT NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"UpdatedAt\" TEXT NOT NULL,\n \"IsDeleted\" INTEGER NOT NULL,\n CONSTRAINT \"FK_Passkeys_Credentials_CredentialId\" FOREIGN KEY (\"CredentialId\") REFERENCES \"Credentials\" (\"Id\") ON DELETE CASCADE\n);\n\nCREATE INDEX \"IX_Passkeys_CredentialId\" ON \"Passkeys\" (\"CredentialId\");\n\nCREATE INDEX \"IX_Passkeys_RpId\" ON \"Passkeys\" (\"RpId\");\n\nINSERT INTO \"__EFMigrationsHistory\" (\"MigrationId\", \"ProductVersion\")\nVALUES ('20251014122838_1.6.0-AddPasskeys', '9.0.4');\n\nALTER TABLE \"TotpCodes\" RENAME COLUMN \"CredentialId\" TO \"ItemId\";\n\nDROP INDEX IF EXISTS \"IX_TotpCodes_CredentialId\";\n\nCREATE INDEX IF NOT EXISTS \"IX_TotpCodes_ItemId\" ON \"TotpCodes\" (\"ItemId\");\n\nALTER TABLE \"Passkeys\" RENAME COLUMN \"CredentialId\" TO \"ItemId\";\n\nDROP INDEX IF EXISTS \"IX_Passkeys_CredentialId\";\n\nCREATE INDEX IF NOT EXISTS \"IX_Passkeys_ItemId\" ON \"Passkeys\" (\"ItemId\");\n\nALTER TABLE \"Attachments\" RENAME COLUMN \"CredentialId\" TO \"ItemId\";\n\nDROP INDEX IF EXISTS \"IX_Attachments_CredentialId\";\n\nCREATE INDEX IF NOT EXISTS \"IX_Attachments_ItemId\" ON \"Attachments\" (\"ItemId\");\n\nCREATE TABLE \"FieldDefinitions\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_FieldDefinitions\" PRIMARY KEY,\n \"FieldType\" TEXT NOT NULL,\n \"Label\" TEXT NOT NULL,\n \"IsMultiValue\" INTEGER NOT NULL,\n \"IsHidden\" INTEGER NOT NULL,\n \"EnableHistory\" INTEGER NOT NULL,\n \"Weight\" INTEGER NOT NULL,\n \"ApplicableToTypes\" TEXT NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"UpdatedAt\" TEXT NOT NULL,\n \"IsDeleted\" INTEGER NOT NULL\n);\n\nCREATE TABLE \"Folders\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_Folders\" PRIMARY KEY,\n \"Name\" TEXT NOT NULL,\n \"ParentFolderId\" TEXT NULL,\n \"Weight\" INTEGER NOT NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"UpdatedAt\" TEXT NOT NULL,\n \"IsDeleted\" INTEGER NOT NULL,\n CONSTRAINT \"FK_Folders_Folders_ParentFolderId\" FOREIGN KEY (\"ParentFolderId\") REFERENCES \"Folders\" (\"Id\") ON DELETE CASCADE\n);\n\nCREATE TABLE \"Logos\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_Logos\" PRIMARY KEY,\n \"Source\" TEXT NOT NULL,\n \"FileData\" BLOB NULL,\n \"MimeType\" TEXT NULL,\n \"FetchedAt\" TEXT NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"UpdatedAt\" TEXT NOT NULL,\n \"IsDeleted\" INTEGER NOT NULL\n);\n\nCREATE TABLE \"Tags\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_Tags\" PRIMARY KEY,\n \"Name\" TEXT NOT NULL,\n \"Color\" TEXT NULL,\n \"DisplayOrder\" INTEGER NOT NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"UpdatedAt\" TEXT NOT NULL,\n \"IsDeleted\" INTEGER NOT NULL\n);\n\nCREATE TABLE \"Items\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_Items\" PRIMARY KEY,\n \"Name\" TEXT NULL,\n \"ItemType\" TEXT NOT NULL,\n \"LogoId\" TEXT NULL,\n \"DeletedAt\" TEXT NULL,\n \"FolderId\" TEXT NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"UpdatedAt\" TEXT NOT NULL,\n \"IsDeleted\" INTEGER NOT NULL,\n CONSTRAINT \"FK_Items_Folders_FolderId\" FOREIGN KEY (\"FolderId\") REFERENCES \"Folders\" (\"Id\") ON DELETE SET NULL,\n CONSTRAINT \"FK_Items_Logos_LogoId\" FOREIGN KEY (\"LogoId\") REFERENCES \"Logos\" (\"Id\") ON DELETE SET NULL\n);\n\nCREATE TABLE \"FieldHistories\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_FieldHistories\" PRIMARY KEY,\n \"ItemId\" TEXT NOT NULL,\n \"FieldDefinitionId\" TEXT NULL,\n \"FieldKey\" TEXT NULL,\n \"ValueSnapshot\" TEXT NOT NULL,\n \"ChangedAt\" TEXT NOT NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"UpdatedAt\" TEXT NOT NULL,\n \"IsDeleted\" INTEGER NOT NULL,\n CONSTRAINT \"FK_FieldHistories_FieldDefinitions_FieldDefinitionId\" FOREIGN KEY (\"FieldDefinitionId\") REFERENCES \"FieldDefinitions\" (\"Id\") ON DELETE CASCADE,\n CONSTRAINT \"FK_FieldHistories_Items_ItemId\" FOREIGN KEY (\"ItemId\") REFERENCES \"Items\" (\"Id\") ON DELETE CASCADE\n);\n\nCREATE TABLE \"FieldValues\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_FieldValues\" PRIMARY KEY,\n \"ItemId\" TEXT NOT NULL,\n \"FieldDefinitionId\" TEXT NULL,\n \"FieldKey\" TEXT NULL,\n \"Value\" TEXT NULL,\n \"Weight\" INTEGER NOT NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"UpdatedAt\" TEXT NOT NULL,\n \"IsDeleted\" INTEGER NOT NULL,\n CONSTRAINT \"FK_FieldValues_FieldDefinitions_FieldDefinitionId\" FOREIGN KEY (\"FieldDefinitionId\") REFERENCES \"FieldDefinitions\" (\"Id\") ON DELETE CASCADE,\n CONSTRAINT \"FK_FieldValues_Items_ItemId\" FOREIGN KEY (\"ItemId\") REFERENCES \"Items\" (\"Id\") ON DELETE CASCADE\n);\n\nCREATE TABLE \"ItemTags\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_ItemTags\" PRIMARY KEY,\n \"ItemId\" TEXT NOT NULL,\n \"TagId\" TEXT NOT NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"UpdatedAt\" TEXT NOT NULL,\n \"IsDeleted\" INTEGER NOT NULL,\n CONSTRAINT \"FK_ItemTags_Items_ItemId\" FOREIGN KEY (\"ItemId\") REFERENCES \"Items\" (\"Id\") ON DELETE CASCADE,\n CONSTRAINT \"FK_ItemTags_Tags_TagId\" FOREIGN KEY (\"TagId\") REFERENCES \"Tags\" (\"Id\") ON DELETE CASCADE\n);\n\nCREATE INDEX \"IX_FieldHistories_FieldDefinitionId\" ON \"FieldHistories\" (\"FieldDefinitionId\");\n\nCREATE INDEX \"IX_FieldHistories_ItemId\" ON \"FieldHistories\" (\"ItemId\");\n\nCREATE INDEX \"IX_FieldValues_FieldDefinitionId\" ON \"FieldValues\" (\"FieldDefinitionId\");\n\nCREATE INDEX \"IX_FieldValues_FieldKey\" ON \"FieldValues\" (\"FieldKey\");\n\nCREATE INDEX \"IX_FieldValues_ItemId\" ON \"FieldValues\" (\"ItemId\");\n\nCREATE INDEX \"IX_FieldValues_ItemId_FieldDefinitionId_Weight\" ON \"FieldValues\" (\"ItemId\", \"FieldDefinitionId\", \"Weight\");\n\nCREATE INDEX \"IX_FieldValues_ItemId_FieldKey\" ON \"FieldValues\" (\"ItemId\", \"FieldKey\");\n\nCREATE INDEX \"IX_Folders_ParentFolderId\" ON \"Folders\" (\"ParentFolderId\");\n\nCREATE INDEX \"IX_Items_FolderId\" ON \"Items\" (\"FolderId\");\n\nCREATE INDEX \"IX_Items_LogoId\" ON \"Items\" (\"LogoId\");\n\nCREATE INDEX \"IX_ItemTags_ItemId\" ON \"ItemTags\" (\"ItemId\");\n\nCREATE UNIQUE INDEX \"IX_ItemTags_ItemId_TagId\" ON \"ItemTags\" (\"ItemId\", \"TagId\");\n\nCREATE INDEX \"IX_ItemTags_TagId\" ON \"ItemTags\" (\"TagId\");\n\nCREATE UNIQUE INDEX \"IX_Logos_Source\" ON \"Logos\" (\"Source\");\n\nCREATE INDEX \"IX_Tags_Name\" ON \"Tags\" (\"Name\");\n\n\n INSERT INTO Items (Id, Name, ItemType, LogoId, FolderId, CreatedAt, UpdatedAt, IsDeleted)\n SELECT\n c.Id,\n s.Name AS Name,\n CASE\n WHEN a.Id IS NOT NULL AND (\n (a.FirstName IS NOT NULL AND a.FirstName != '') OR\n (a.LastName IS NOT NULL AND a.LastName != '') OR\n (a.Gender IS NOT NULL AND a.Gender != '') OR\n (a.BirthDate IS NOT NULL AND a.BirthDate != '' AND a.BirthDate NOT LIKE '0001-%')\n ) THEN 'Alias'\n ELSE 'Login'\n END AS ItemType,\n NULL AS LogoId,\n NULL AS FolderId,\n c.CreatedAt,\n c.UpdatedAt,\n c.IsDeleted\n FROM Credentials c\n LEFT JOIN Services s ON s.Id = c.ServiceId\n LEFT JOIN Aliases a ON a.Id = c.AliasId;\n \n\n\n INSERT INTO Logos (Id, Source, FileData, MimeType, FetchedAt, CreatedAt, UpdatedAt, IsDeleted)\n SELECT\n UPPER(SUBSTR(hex(randomblob(4)), 1, 8) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(6)), 1, 12)) AS Id,\n -- Extract and normalize hostname: remove protocol, path, lowercase, and www. prefix\n REPLACE(\n LOWER(\n SUBSTR(\n CASE\n WHEN s.Url LIKE 'https://%' THEN SUBSTR(s.Url, 9)\n WHEN s.Url LIKE 'http://%' THEN SUBSTR(s.Url, 8)\n ELSE s.Url\n END,\n 1,\n CASE\n WHEN INSTR(\n CASE\n WHEN s.Url LIKE 'https://%' THEN SUBSTR(s.Url, 9)\n WHEN s.Url LIKE 'http://%' THEN SUBSTR(s.Url, 8)\n ELSE s.Url\n END, '/') > 0\n THEN INSTR(\n CASE\n WHEN s.Url LIKE 'https://%' THEN SUBSTR(s.Url, 9)\n WHEN s.Url LIKE 'http://%' THEN SUBSTR(s.Url, 8)\n ELSE s.Url\n END, '/') - 1\n ELSE LENGTH(\n CASE\n WHEN s.Url LIKE 'https://%' THEN SUBSTR(s.Url, 9)\n WHEN s.Url LIKE 'http://%' THEN SUBSTR(s.Url, 8)\n ELSE s.Url\n END)\n END\n )\n ),\n 'www.', ''\n ) AS Source,\n s.Logo AS FileData,\n 'image/png' AS MimeType,\n NULL AS FetchedAt,\n MIN(s.CreatedAt) AS CreatedAt,\n MAX(s.UpdatedAt) AS UpdatedAt,\n 0 AS IsDeleted\n FROM Services s\n WHERE s.Logo IS NOT NULL AND s.Url IS NOT NULL AND s.Url != ''\n GROUP BY REPLACE(\n LOWER(\n SUBSTR(\n CASE\n WHEN s.Url LIKE 'https://%' THEN SUBSTR(s.Url, 9)\n WHEN s.Url LIKE 'http://%' THEN SUBSTR(s.Url, 8)\n ELSE s.Url\n END,\n 1,\n CASE\n WHEN INSTR(\n CASE\n WHEN s.Url LIKE 'https://%' THEN SUBSTR(s.Url, 9)\n WHEN s.Url LIKE 'http://%' THEN SUBSTR(s.Url, 8)\n ELSE s.Url\n END, '/') > 0\n THEN INSTR(\n CASE\n WHEN s.Url LIKE 'https://%' THEN SUBSTR(s.Url, 9)\n WHEN s.Url LIKE 'http://%' THEN SUBSTR(s.Url, 8)\n ELSE s.Url\n END, '/') - 1\n ELSE LENGTH(\n CASE\n WHEN s.Url LIKE 'https://%' THEN SUBSTR(s.Url, 9)\n WHEN s.Url LIKE 'http://%' THEN SUBSTR(s.Url, 8)\n ELSE s.Url\n END)\n END\n )\n ),\n 'www.', ''\n );\n \n\n\n UPDATE Items\n SET LogoId = (\n SELECT l.Id FROM Logos l\n INNER JOIN Services s ON REPLACE(\n LOWER(\n SUBSTR(\n CASE\n WHEN s.Url LIKE 'https://%' THEN SUBSTR(s.Url, 9)\n WHEN s.Url LIKE 'http://%' THEN SUBSTR(s.Url, 8)\n ELSE s.Url\n END,\n 1,\n CASE\n WHEN INSTR(\n CASE\n WHEN s.Url LIKE 'https://%' THEN SUBSTR(s.Url, 9)\n WHEN s.Url LIKE 'http://%' THEN SUBSTR(s.Url, 8)\n ELSE s.Url\n END, '/') > 0\n THEN INSTR(\n CASE\n WHEN s.Url LIKE 'https://%' THEN SUBSTR(s.Url, 9)\n WHEN s.Url LIKE 'http://%' THEN SUBSTR(s.Url, 8)\n ELSE s.Url\n END, '/') - 1\n ELSE LENGTH(\n CASE\n WHEN s.Url LIKE 'https://%' THEN SUBSTR(s.Url, 9)\n WHEN s.Url LIKE 'http://%' THEN SUBSTR(s.Url, 8)\n ELSE s.Url\n END)\n END\n )\n ),\n 'www.', ''\n ) = l.Source\n INNER JOIN Credentials c ON c.ServiceId = s.Id\n WHERE c.Id = Items.Id\n LIMIT 1\n )\n WHERE EXISTS (\n SELECT 1 FROM Credentials c\n INNER JOIN Services s ON s.Id = c.ServiceId\n WHERE c.Id = Items.Id AND s.Logo IS NOT NULL\n );\n \n\n\n INSERT INTO FieldValues (Id, ItemId, FieldDefinitionId, FieldKey, Value, Weight, CreatedAt, UpdatedAt, IsDeleted)\n SELECT\n UPPER(SUBSTR(hex(randomblob(4)), 1, 8) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(6)), 1, 12)) AS Id,\n c.Id AS ItemId,\n NULL AS FieldDefinitionId,\n 'login.url' AS FieldKey,\n s.Url AS Value,\n 0 AS Weight,\n s.UpdatedAt AS CreatedAt,\n s.UpdatedAt AS UpdatedAt,\n 0 AS IsDeleted\n FROM Credentials c\n INNER JOIN Services s ON s.Id = c.ServiceId\n WHERE s.Url IS NOT NULL AND s.Url != '';\n \n\n\n INSERT INTO FieldValues (Id, ItemId, FieldDefinitionId, FieldKey, Value, Weight, CreatedAt, UpdatedAt, IsDeleted)\n SELECT\n UPPER(SUBSTR(hex(randomblob(4)), 1, 8) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(6)), 1, 12)) AS Id,\n c.Id AS ItemId,\n NULL AS FieldDefinitionId,\n 'login.username' AS FieldKey,\n c.Username AS Value,\n 0 AS Weight,\n c.UpdatedAt AS CreatedAt,\n c.UpdatedAt AS UpdatedAt,\n 0 AS IsDeleted\n FROM Credentials c\n WHERE c.Username IS NOT NULL AND c.Username != '';\n \n\n\n INSERT INTO FieldValues (Id, ItemId, FieldDefinitionId, FieldKey, Value, Weight, CreatedAt, UpdatedAt, IsDeleted)\n SELECT\n UPPER(SUBSTR(hex(randomblob(4)), 1, 8) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(6)), 1, 12)) AS Id,\n c.Id AS ItemId,\n NULL AS FieldDefinitionId,\n 'login.notes' AS FieldKey,\n c.Notes AS Value,\n 0 AS Weight,\n c.UpdatedAt AS CreatedAt,\n c.UpdatedAt AS UpdatedAt,\n 0 AS IsDeleted\n FROM Credentials c\n WHERE c.Notes IS NOT NULL AND c.Notes != '';\n \n\n\n INSERT INTO FieldValues (Id, ItemId, FieldDefinitionId, FieldKey, Value, Weight, CreatedAt, UpdatedAt, IsDeleted)\n SELECT\n UPPER(SUBSTR(hex(randomblob(4)), 1, 8) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(6)), 1, 12)) AS Id,\n p.CredentialId AS ItemId,\n NULL AS FieldDefinitionId,\n 'login.password' AS FieldKey,\n p.Value AS Value,\n 0 AS Weight,\n p.UpdatedAt AS CreatedAt,\n p.UpdatedAt AS UpdatedAt,\n 0 AS IsDeleted\n FROM Passwords p\n INNER JOIN (\n SELECT CredentialId, MAX(UpdatedAt) AS MaxUpdated, MAX(Id) AS MaxId\n FROM Passwords\n WHERE IsDeleted = 0\n GROUP BY CredentialId\n ) pm ON p.CredentialId = pm.CredentialId AND p.UpdatedAt = pm.MaxUpdated AND p.Id = pm.MaxId\n WHERE p.IsDeleted = 0;\n \n\n\n INSERT INTO FieldValues (Id, ItemId, FieldDefinitionId, FieldKey, Value, Weight, CreatedAt, UpdatedAt, IsDeleted)\n SELECT\n UPPER(SUBSTR(hex(randomblob(4)), 1, 8) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(6)), 1, 12)) AS Id,\n c.Id AS ItemId,\n NULL AS FieldDefinitionId,\n 'login.email' AS FieldKey,\n a.Email AS Value,\n 0 AS Weight,\n a.UpdatedAt AS CreatedAt,\n a.UpdatedAt AS UpdatedAt,\n 0 AS IsDeleted\n FROM Credentials c\n INNER JOIN Aliases a ON a.Id = c.AliasId\n WHERE a.Email IS NOT NULL AND a.Email != '';\n \n\n\n INSERT INTO FieldValues (Id, ItemId, FieldDefinitionId, FieldKey, Value, Weight, CreatedAt, UpdatedAt, IsDeleted)\n SELECT\n UPPER(SUBSTR(hex(randomblob(4)), 1, 8) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(6)), 1, 12)) AS Id,\n c.Id AS ItemId,\n NULL AS FieldDefinitionId,\n 'alias.first_name' AS FieldKey,\n a.FirstName AS Value,\n 0 AS Weight,\n a.UpdatedAt AS CreatedAt,\n a.UpdatedAt AS UpdatedAt,\n 0 AS IsDeleted\n FROM Credentials c\n INNER JOIN Aliases a ON a.Id = c.AliasId\n WHERE a.FirstName IS NOT NULL AND a.FirstName != '';\n \n\n\n INSERT INTO FieldValues (Id, ItemId, FieldDefinitionId, FieldKey, Value, Weight, CreatedAt, UpdatedAt, IsDeleted)\n SELECT\n UPPER(SUBSTR(hex(randomblob(4)), 1, 8) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(6)), 1, 12)) AS Id,\n c.Id AS ItemId,\n NULL AS FieldDefinitionId,\n 'alias.last_name' AS FieldKey,\n a.LastName AS Value,\n 0 AS Weight,\n a.UpdatedAt AS CreatedAt,\n a.UpdatedAt AS UpdatedAt,\n 0 AS IsDeleted\n FROM Credentials c\n INNER JOIN Aliases a ON a.Id = c.AliasId\n WHERE a.LastName IS NOT NULL AND a.LastName != '';\n \n\n\n INSERT INTO FieldValues (Id, ItemId, FieldDefinitionId, FieldKey, Value, Weight, CreatedAt, UpdatedAt, IsDeleted)\n SELECT\n UPPER(SUBSTR(hex(randomblob(4)), 1, 8) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(6)), 1, 12)) AS Id,\n c.Id AS ItemId,\n NULL AS FieldDefinitionId,\n 'alias.gender' AS FieldKey,\n a.Gender AS Value,\n 0 AS Weight,\n a.UpdatedAt AS CreatedAt,\n a.UpdatedAt AS UpdatedAt,\n 0 AS IsDeleted\n FROM Credentials c\n INNER JOIN Aliases a ON a.Id = c.AliasId\n WHERE a.Gender IS NOT NULL AND a.Gender != '';\n \n\n\n INSERT INTO FieldValues (Id, ItemId, FieldDefinitionId, FieldKey, Value, Weight, CreatedAt, UpdatedAt, IsDeleted)\n SELECT\n UPPER(SUBSTR(hex(randomblob(4)), 1, 8) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(6)), 1, 12)) AS Id,\n c.Id AS ItemId,\n NULL AS FieldDefinitionId,\n 'alias.birthdate' AS FieldKey,\n SUBSTR(a.BirthDate, 1, 10) AS Value,\n 0 AS Weight,\n a.UpdatedAt AS CreatedAt,\n a.UpdatedAt AS UpdatedAt,\n 0 AS IsDeleted\n FROM Credentials c\n INNER JOIN Aliases a ON a.Id = c.AliasId\n WHERE a.BirthDate IS NOT NULL AND a.BirthDate != '' AND a.BirthDate NOT LIKE '0001-%';\n \n\nDROP TABLE \"Passwords\";\n\nDROP TABLE \"Credentials\";\n\nDROP TABLE \"Aliases\";\n\nDROP TABLE \"Services\";\n\nCREATE TABLE \"ef_temp_Attachments\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_Attachments\" PRIMARY KEY,\n \"Blob\" BLOB NOT NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"Filename\" TEXT NOT NULL,\n \"IsDeleted\" INTEGER NOT NULL,\n \"ItemId\" TEXT NOT NULL,\n \"UpdatedAt\" TEXT NOT NULL,\n CONSTRAINT \"FK_Attachments_Items_ItemId\" FOREIGN KEY (\"ItemId\") REFERENCES \"Items\" (\"Id\") ON DELETE CASCADE\n);\n\nINSERT INTO \"ef_temp_Attachments\" (\"Id\", \"Blob\", \"CreatedAt\", \"Filename\", \"IsDeleted\", \"ItemId\", \"UpdatedAt\")\nSELECT \"Id\", \"Blob\", \"CreatedAt\", \"Filename\", \"IsDeleted\", \"ItemId\", \"UpdatedAt\"\nFROM \"Attachments\";\n\nCREATE TABLE \"ef_temp_Passkeys\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_Passkeys\" PRIMARY KEY,\n \"AdditionalData\" BLOB NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"DisplayName\" TEXT NOT NULL,\n \"IsDeleted\" INTEGER NOT NULL,\n \"ItemId\" TEXT NOT NULL,\n \"PrfKey\" BLOB NULL,\n \"PrivateKey\" TEXT NOT NULL,\n \"PublicKey\" TEXT NOT NULL,\n \"RpId\" TEXT COLLATE NOCASE NOT NULL,\n \"UpdatedAt\" TEXT NOT NULL,\n \"UserHandle\" BLOB NOT NULL,\n CONSTRAINT \"FK_Passkeys_Items_ItemId\" FOREIGN KEY (\"ItemId\") REFERENCES \"Items\" (\"Id\") ON DELETE CASCADE\n);\n\nINSERT INTO \"ef_temp_Passkeys\" (\"Id\", \"AdditionalData\", \"CreatedAt\", \"DisplayName\", \"IsDeleted\", \"ItemId\", \"PrfKey\", \"PrivateKey\", \"PublicKey\", \"RpId\", \"UpdatedAt\", \"UserHandle\")\nSELECT \"Id\", \"AdditionalData\", \"CreatedAt\", \"DisplayName\", \"IsDeleted\", \"ItemId\", \"PrfKey\", \"PrivateKey\", \"PublicKey\", \"RpId\", \"UpdatedAt\", \"UserHandle\"\nFROM \"Passkeys\";\n\nCREATE TABLE \"ef_temp_TotpCodes\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_TotpCodes\" PRIMARY KEY,\n \"CreatedAt\" TEXT NOT NULL,\n \"IsDeleted\" INTEGER NOT NULL,\n \"ItemId\" TEXT NOT NULL,\n \"Name\" TEXT NOT NULL,\n \"SecretKey\" TEXT NOT NULL,\n \"UpdatedAt\" TEXT NOT NULL,\n CONSTRAINT \"FK_TotpCodes_Items_ItemId\" FOREIGN KEY (\"ItemId\") REFERENCES \"Items\" (\"Id\") ON DELETE CASCADE\n);\n\nINSERT INTO \"ef_temp_TotpCodes\" (\"Id\", \"CreatedAt\", \"IsDeleted\", \"ItemId\", \"Name\", \"SecretKey\", \"UpdatedAt\")\nSELECT \"Id\", \"CreatedAt\", \"IsDeleted\", \"ItemId\", \"Name\", \"SecretKey\", \"UpdatedAt\"\nFROM \"TotpCodes\";\n\nCOMMIT;\n\nPRAGMA foreign_keys = 0;\n\nBEGIN TRANSACTION;\nDROP TABLE \"Attachments\";\n\nALTER TABLE \"ef_temp_Attachments\" RENAME TO \"Attachments\";\n\nDROP TABLE \"Passkeys\";\n\nALTER TABLE \"ef_temp_Passkeys\" RENAME TO \"Passkeys\";\n\nDROP TABLE \"TotpCodes\";\n\nALTER TABLE \"ef_temp_TotpCodes\" RENAME TO \"TotpCodes\";\n\nCOMMIT;\n\nPRAGMA foreign_keys = 1;\n\nBEGIN TRANSACTION;\nCREATE INDEX \"IX_Attachments_ItemId\" ON \"Attachments\" (\"ItemId\");\n\nCREATE INDEX \"IX_Passkeys_ItemId\" ON \"Passkeys\" (\"ItemId\");\n\nCREATE INDEX \"IX_Passkeys_RpId\" ON \"Passkeys\" (\"RpId\");\n\nCREATE INDEX \"IX_TotpCodes_ItemId\" ON \"TotpCodes\" (\"ItemId\");\n\nCOMMIT;\n\nINSERT INTO \"__EFMigrationsHistory\" (\"MigrationId\", \"ProductVersion\")\nVALUES ('20251213111207_1.7.0-FieldBasedDataModelUpdate', '9.0.4');\n\nBEGIN TRANSACTION;\nINSERT INTO \"__EFMigrationsHistory\" (\"MigrationId\", \"ProductVersion\")\nVALUES ('20260130221620_2.0.0-MajorVersionBump', '9.0.4');\n\nCOMMIT;\n"; /** * Individual migration SQL scripts * Auto-generated from EF Core migrations diff --git a/apps/server/AliasVault.Client/wwwroot/js/dist/core/vault/index.d.ts b/apps/server/AliasVault.Client/wwwroot/js/dist/core/vault/index.d.ts index 033a999f0..0ee327dbe 100644 --- a/apps/server/AliasVault.Client/wwwroot/js/dist/core/vault/index.d.ts +++ b/apps/server/AliasVault.Client/wwwroot/js/dist/core/vault/index.d.ts @@ -122,7 +122,7 @@ declare const VAULT_VERSIONS: VaultVersion[]; * Complete database schema SQL (latest version) * Auto-generated from EF Core migrations */ -declare const COMPLETE_SCHEMA_SQL = "\n\uFEFFCREATE TABLE IF NOT EXISTS \"__EFMigrationsHistory\" (\n \"MigrationId\" TEXT NOT NULL CONSTRAINT \"PK___EFMigrationsHistory\" PRIMARY KEY,\n \"ProductVersion\" TEXT NOT NULL\n);\n\nBEGIN TRANSACTION;\nCREATE TABLE \"Aliases\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_Aliases\" PRIMARY KEY,\n \"Gender\" VARCHAR NULL,\n \"FirstName\" VARCHAR NULL,\n \"LastName\" VARCHAR NULL,\n \"NickName\" VARCHAR NULL,\n \"BirthDate\" TEXT NOT NULL,\n \"AddressStreet\" VARCHAR NULL,\n \"AddressCity\" VARCHAR NULL,\n \"AddressState\" VARCHAR NULL,\n \"AddressZipCode\" VARCHAR NULL,\n \"AddressCountry\" VARCHAR NULL,\n \"Hobbies\" TEXT NULL,\n \"EmailPrefix\" TEXT NULL,\n \"PhoneMobile\" TEXT NULL,\n \"BankAccountIBAN\" TEXT NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"UpdatedAt\" TEXT NOT NULL\n);\n\nCREATE TABLE \"Services\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_Services\" PRIMARY KEY,\n \"Name\" TEXT NULL,\n \"Url\" TEXT NULL,\n \"Logo\" BLOB NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"UpdatedAt\" TEXT NOT NULL\n);\n\nCREATE TABLE \"Credentials\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_Credentials\" PRIMARY KEY,\n \"AliasId\" TEXT NOT NULL,\n \"Notes\" TEXT NULL,\n \"Username\" TEXT NOT NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"UpdatedAt\" TEXT NOT NULL,\n \"ServiceId\" TEXT NOT NULL,\n CONSTRAINT \"FK_Credentials_Aliases_AliasId\" FOREIGN KEY (\"AliasId\") REFERENCES \"Aliases\" (\"Id\") ON DELETE CASCADE,\n CONSTRAINT \"FK_Credentials_Services_ServiceId\" FOREIGN KEY (\"ServiceId\") REFERENCES \"Services\" (\"Id\") ON DELETE CASCADE\n);\n\nCREATE TABLE \"Attachment\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_Attachment\" PRIMARY KEY,\n \"Filename\" TEXT NOT NULL,\n \"Blob\" BLOB NOT NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"UpdatedAt\" TEXT NOT NULL,\n \"CredentialId\" TEXT NOT NULL,\n CONSTRAINT \"FK_Attachment_Credentials_CredentialId\" FOREIGN KEY (\"CredentialId\") REFERENCES \"Credentials\" (\"Id\") ON DELETE CASCADE\n);\n\nCREATE TABLE \"Passwords\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_Passwords\" PRIMARY KEY,\n \"Value\" TEXT NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"UpdatedAt\" TEXT NOT NULL,\n \"CredentialId\" TEXT NOT NULL,\n CONSTRAINT \"FK_Passwords_Credentials_CredentialId\" FOREIGN KEY (\"CredentialId\") REFERENCES \"Credentials\" (\"Id\") ON DELETE CASCADE\n);\n\nCREATE INDEX \"IX_Attachment_CredentialId\" ON \"Attachment\" (\"CredentialId\");\n\nCREATE INDEX \"IX_Credentials_AliasId\" ON \"Credentials\" (\"AliasId\");\n\nCREATE INDEX \"IX_Credentials_ServiceId\" ON \"Credentials\" (\"ServiceId\");\n\nCREATE INDEX \"IX_Passwords_CredentialId\" ON \"Passwords\" (\"CredentialId\");\n\nINSERT INTO \"__EFMigrationsHistory\" (\"MigrationId\", \"ProductVersion\")\nVALUES ('20240708094944_1.0.0-InitialMigration', '9.0.4');\n\nINSERT INTO \"__EFMigrationsHistory\" (\"MigrationId\", \"ProductVersion\")\nVALUES ('20240708224522_1.0.1-EmptyTestMigration', '9.0.4');\n\nALTER TABLE \"Aliases\" RENAME COLUMN \"EmailPrefix\" TO \"Email\";\n\nINSERT INTO \"__EFMigrationsHistory\" (\"MigrationId\", \"ProductVersion\")\nVALUES ('20240711204207_1.0.2-ChangeEmailColumn', '9.0.4');\n\nCREATE TABLE \"EncryptionKeys\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_EncryptionKeys\" PRIMARY KEY,\n \"PublicKey\" TEXT NOT NULL,\n \"PrivateKey\" TEXT NOT NULL,\n \"IsPrimary\" INTEGER NOT NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"UpdatedAt\" TEXT NOT NULL\n);\n\nINSERT INTO \"__EFMigrationsHistory\" (\"MigrationId\", \"ProductVersion\")\nVALUES ('20240729105618_1.1.0-AddPkiTables', '9.0.4');\n\nCREATE TABLE \"Settings\" (\n \"Key\" TEXT NOT NULL CONSTRAINT \"PK_Settings\" PRIMARY KEY,\n \"Value\" TEXT NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"UpdatedAt\" TEXT NOT NULL\n);\n\nINSERT INTO \"__EFMigrationsHistory\" (\"MigrationId\", \"ProductVersion\")\nVALUES ('20240805073413_1.2.0-AddSettingsTable', '9.0.4');\n\nCREATE TABLE \"ef_temp_Aliases\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_Aliases\" PRIMARY KEY,\n \"BirthDate\" TEXT NOT NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"Email\" TEXT NULL,\n \"FirstName\" VARCHAR NULL,\n \"Gender\" VARCHAR NULL,\n \"LastName\" VARCHAR NULL,\n \"NickName\" VARCHAR NULL,\n \"UpdatedAt\" TEXT NOT NULL\n);\n\nINSERT INTO \"ef_temp_Aliases\" (\"Id\", \"BirthDate\", \"CreatedAt\", \"Email\", \"FirstName\", \"Gender\", \"LastName\", \"NickName\", \"UpdatedAt\")\nSELECT \"Id\", \"BirthDate\", \"CreatedAt\", \"Email\", \"FirstName\", \"Gender\", \"LastName\", \"NickName\", \"UpdatedAt\"\nFROM \"Aliases\";\n\nCOMMIT;\n\nPRAGMA foreign_keys = 0;\n\nBEGIN TRANSACTION;\nDROP TABLE \"Aliases\";\n\nALTER TABLE \"ef_temp_Aliases\" RENAME TO \"Aliases\";\n\nCOMMIT;\n\nPRAGMA foreign_keys = 1;\n\nINSERT INTO \"__EFMigrationsHistory\" (\"MigrationId\", \"ProductVersion\")\nVALUES ('20240805122422_1.3.0-UpdateIdentityStructure', '9.0.4');\n\nBEGIN TRANSACTION;\nCREATE TABLE \"ef_temp_Credentials\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_Credentials\" PRIMARY KEY,\n \"AliasId\" TEXT NOT NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"Notes\" TEXT NULL,\n \"ServiceId\" TEXT NOT NULL,\n \"UpdatedAt\" TEXT NOT NULL,\n \"Username\" TEXT NULL,\n CONSTRAINT \"FK_Credentials_Aliases_AliasId\" FOREIGN KEY (\"AliasId\") REFERENCES \"Aliases\" (\"Id\") ON DELETE CASCADE,\n CONSTRAINT \"FK_Credentials_Services_ServiceId\" FOREIGN KEY (\"ServiceId\") REFERENCES \"Services\" (\"Id\") ON DELETE CASCADE\n);\n\nINSERT INTO \"ef_temp_Credentials\" (\"Id\", \"AliasId\", \"CreatedAt\", \"Notes\", \"ServiceId\", \"UpdatedAt\", \"Username\")\nSELECT \"Id\", \"AliasId\", \"CreatedAt\", \"Notes\", \"ServiceId\", \"UpdatedAt\", \"Username\"\nFROM \"Credentials\";\n\nCOMMIT;\n\nPRAGMA foreign_keys = 0;\n\nBEGIN TRANSACTION;\nDROP TABLE \"Credentials\";\n\nALTER TABLE \"ef_temp_Credentials\" RENAME TO \"Credentials\";\n\nCOMMIT;\n\nPRAGMA foreign_keys = 1;\n\nBEGIN TRANSACTION;\nCREATE INDEX \"IX_Credentials_AliasId\" ON \"Credentials\" (\"AliasId\");\n\nCREATE INDEX \"IX_Credentials_ServiceId\" ON \"Credentials\" (\"ServiceId\");\n\nCOMMIT;\n\nINSERT INTO \"__EFMigrationsHistory\" (\"MigrationId\", \"ProductVersion\")\nVALUES ('20240812141727_1.3.1-MakeUsernameOptional', '9.0.4');\n\nBEGIN TRANSACTION;\nALTER TABLE \"Settings\" ADD \"IsDeleted\" INTEGER NOT NULL DEFAULT 0;\n\nALTER TABLE \"Services\" ADD \"IsDeleted\" INTEGER NOT NULL DEFAULT 0;\n\nALTER TABLE \"Passwords\" ADD \"IsDeleted\" INTEGER NOT NULL DEFAULT 0;\n\nALTER TABLE \"EncryptionKeys\" ADD \"IsDeleted\" INTEGER NOT NULL DEFAULT 0;\n\nALTER TABLE \"Credentials\" ADD \"IsDeleted\" INTEGER NOT NULL DEFAULT 0;\n\nALTER TABLE \"Attachment\" ADD \"IsDeleted\" INTEGER NOT NULL DEFAULT 0;\n\nALTER TABLE \"Aliases\" ADD \"IsDeleted\" INTEGER NOT NULL DEFAULT 0;\n\nINSERT INTO \"__EFMigrationsHistory\" (\"MigrationId\", \"ProductVersion\")\nVALUES ('20240916105320_1.4.0-AddSyncSupport', '9.0.4');\n\nALTER TABLE \"Attachment\" RENAME TO \"Attachments\";\n\nCREATE TABLE \"ef_temp_Attachments\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_Attachments\" PRIMARY KEY,\n \"Blob\" BLOB NOT NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"CredentialId\" TEXT NOT NULL,\n \"Filename\" TEXT NOT NULL,\n \"IsDeleted\" INTEGER NOT NULL,\n \"UpdatedAt\" TEXT NOT NULL,\n CONSTRAINT \"FK_Attachments_Credentials_CredentialId\" FOREIGN KEY (\"CredentialId\") REFERENCES \"Credentials\" (\"Id\") ON DELETE CASCADE\n);\n\nINSERT INTO \"ef_temp_Attachments\" (\"Id\", \"Blob\", \"CreatedAt\", \"CredentialId\", \"Filename\", \"IsDeleted\", \"UpdatedAt\")\nSELECT \"Id\", \"Blob\", \"CreatedAt\", \"CredentialId\", \"Filename\", \"IsDeleted\", \"UpdatedAt\"\nFROM \"Attachments\";\n\nCOMMIT;\n\nPRAGMA foreign_keys = 0;\n\nBEGIN TRANSACTION;\nDROP TABLE \"Attachments\";\n\nALTER TABLE \"ef_temp_Attachments\" RENAME TO \"Attachments\";\n\nCOMMIT;\n\nPRAGMA foreign_keys = 1;\n\nBEGIN TRANSACTION;\nCREATE INDEX \"IX_Attachments_CredentialId\" ON \"Attachments\" (\"CredentialId\");\n\nCOMMIT;\n\nINSERT INTO \"__EFMigrationsHistory\" (\"MigrationId\", \"ProductVersion\")\nVALUES ('20240917191243_1.4.1-RenameAttachmentsPlural', '9.0.4');\n\nBEGIN TRANSACTION;\nCREATE TABLE \"TotpCodes\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_TotpCodes\" PRIMARY KEY,\n \"Name\" TEXT NOT NULL,\n \"SecretKey\" TEXT NOT NULL,\n \"CredentialId\" TEXT NOT NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"UpdatedAt\" TEXT NOT NULL,\n \"IsDeleted\" INTEGER NOT NULL,\n CONSTRAINT \"FK_TotpCodes_Credentials_CredentialId\" FOREIGN KEY (\"CredentialId\") REFERENCES \"Credentials\" (\"Id\") ON DELETE CASCADE\n);\n\nCREATE INDEX \"IX_TotpCodes_CredentialId\" ON \"TotpCodes\" (\"CredentialId\");\n\nINSERT INTO \"__EFMigrationsHistory\" (\"MigrationId\", \"ProductVersion\")\nVALUES ('20250310131554_1.5.0-AddTotpCodes', '9.0.4');\n\n\nPRAGMA foreign_keys = OFF;\n\n-- Clean up any existing temp tables first\nDROP TABLE IF EXISTS \"__EFMigrationsHistory_temp\";\nDROP TABLE IF EXISTS \"Aliases_temp\";\nDROP TABLE IF EXISTS \"Services_temp\";\nDROP TABLE IF EXISTS \"EncryptionKeys_temp\";\nDROP TABLE IF EXISTS \"Settings_temp\";\nDROP TABLE IF EXISTS \"Credentials_temp\";\nDROP TABLE IF EXISTS \"Attachments_temp\";\nDROP TABLE IF EXISTS \"Passwords_temp\";\nDROP TABLE IF EXISTS \"TotpCodes_temp\";\n\n-- Create backup tables for all data\nCREATE TABLE \"__EFMigrationsHistory_temp\" AS SELECT * FROM \"__EFMigrationsHistory\";\nCREATE TABLE \"Aliases_temp\" AS SELECT * FROM \"Aliases\";\nCREATE TABLE \"Services_temp\" AS SELECT * FROM \"Services\";\nCREATE TABLE \"EncryptionKeys_temp\" AS SELECT * FROM \"EncryptionKeys\";\nCREATE TABLE \"Settings_temp\" AS SELECT * FROM \"Settings\";\nCREATE TABLE \"Credentials_temp\" AS SELECT * FROM \"Credentials\";\nCREATE TABLE \"Attachments_temp\" AS SELECT * FROM \"Attachments\";\nCREATE TABLE \"Passwords_temp\" AS SELECT * FROM \"Passwords\";\nCREATE TABLE \"TotpCodes_temp\" AS SELECT * FROM \"TotpCodes\";\n\n-- Delete orphaned records that do not have a valid FK to the credential object\nDELETE FROM \"Attachments_temp\" WHERE \"CredentialId\" NOT IN (SELECT \"Id\" FROM \"Credentials_temp\");\nDELETE FROM \"Passwords_temp\" WHERE \"CredentialId\" NOT IN (SELECT \"Id\" FROM \"Credentials_temp\");\nDELETE FROM \"TotpCodes_temp\" WHERE \"CredentialId\" NOT IN (SELECT \"Id\" FROM \"Credentials_temp\");\n\n-- Delete orphaned credentials that do not have valid FKs to alias or service objects\nDELETE FROM \"Credentials_temp\" WHERE \"AliasId\" NOT IN (SELECT \"Id\" FROM \"Aliases_temp\");\nDELETE FROM \"Credentials_temp\" WHERE \"ServiceId\" NOT IN (SELECT \"Id\" FROM \"Services_temp\");\n\n-- After cleaning credentials, clean dependent tables again in case we removed credentials\nDELETE FROM \"Attachments_temp\" WHERE \"CredentialId\" NOT IN (SELECT \"Id\" FROM \"Credentials_temp\");\nDELETE FROM \"Passwords_temp\" WHERE \"CredentialId\" NOT IN (SELECT \"Id\" FROM \"Credentials_temp\");\nDELETE FROM \"TotpCodes_temp\" WHERE \"CredentialId\" NOT IN (SELECT \"Id\" FROM \"Credentials_temp\");\n\n-- Drop all existing tables\nDROP TABLE \"TotpCodes\";\nDROP TABLE \"Passwords\";\nDROP TABLE \"Attachments\";\nDROP TABLE \"Credentials\";\nDROP TABLE \"Settings\";\nDROP TABLE \"EncryptionKeys\";\nDROP TABLE \"Services\";\nDROP TABLE \"Aliases\";\nDROP TABLE \"__EFMigrationsHistory\";\n\n-- Recreate tables with proper constraints (no dependencies first)\nCREATE TABLE \"__EFMigrationsHistory\" (\n \"MigrationId\" TEXT NOT NULL CONSTRAINT \"PK___EFMigrationsHistory\" PRIMARY KEY,\n \"ProductVersion\" TEXT NOT NULL\n);\n\nCREATE TABLE \"Aliases\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_Aliases\" PRIMARY KEY,\n \"BirthDate\" TEXT NOT NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"Email\" TEXT NULL,\n \"FirstName\" VARCHAR NULL,\n \"Gender\" VARCHAR NULL,\n \"LastName\" VARCHAR NULL,\n \"NickName\" VARCHAR NULL,\n \"UpdatedAt\" TEXT NOT NULL,\n \"IsDeleted\" INTEGER NOT NULL DEFAULT 0\n);\n\nCREATE TABLE \"Services\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_Services\" PRIMARY KEY,\n \"Name\" TEXT NULL,\n \"Url\" TEXT NULL,\n \"Logo\" BLOB NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"UpdatedAt\" TEXT NOT NULL,\n \"IsDeleted\" INTEGER NOT NULL DEFAULT 0\n);\n\nCREATE TABLE \"EncryptionKeys\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_EncryptionKeys\" PRIMARY KEY,\n \"PublicKey\" TEXT NOT NULL,\n \"PrivateKey\" TEXT NOT NULL,\n \"IsPrimary\" INTEGER NOT NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"UpdatedAt\" TEXT NOT NULL,\n \"IsDeleted\" INTEGER NOT NULL DEFAULT 0\n);\n\nCREATE TABLE \"Settings\" (\n \"Key\" TEXT NOT NULL CONSTRAINT \"PK_Settings\" PRIMARY KEY,\n \"Value\" TEXT NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"UpdatedAt\" TEXT NOT NULL,\n \"IsDeleted\" INTEGER NOT NULL DEFAULT 0\n);\n\n-- Tables with foreign keys\nCREATE TABLE \"Credentials\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_Credentials\" PRIMARY KEY,\n \"AliasId\" TEXT NOT NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"Notes\" TEXT NULL,\n \"ServiceId\" TEXT NOT NULL,\n \"UpdatedAt\" TEXT NOT NULL,\n \"Username\" TEXT NULL,\n \"IsDeleted\" INTEGER NOT NULL DEFAULT 0,\n CONSTRAINT \"FK_Credentials_Aliases_AliasId\" FOREIGN KEY (\"AliasId\") REFERENCES \"Aliases\" (\"Id\") ON DELETE CASCADE,\n CONSTRAINT \"FK_Credentials_Services_ServiceId\" FOREIGN KEY (\"ServiceId\") REFERENCES \"Services\" (\"Id\") ON DELETE CASCADE\n);\n\nCREATE TABLE \"Attachments\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_Attachments\" PRIMARY KEY,\n \"Blob\" BLOB NOT NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"CredentialId\" TEXT NOT NULL,\n \"Filename\" TEXT NOT NULL,\n \"IsDeleted\" INTEGER NOT NULL DEFAULT 0,\n \"UpdatedAt\" TEXT NOT NULL,\n CONSTRAINT \"FK_Attachments_Credentials_CredentialId\" FOREIGN KEY (\"CredentialId\") REFERENCES \"Credentials\" (\"Id\") ON DELETE CASCADE\n);\n\nCREATE TABLE \"Passwords\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_Passwords\" PRIMARY KEY,\n \"Value\" TEXT NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"UpdatedAt\" TEXT NOT NULL,\n \"CredentialId\" TEXT NOT NULL,\n \"IsDeleted\" INTEGER NOT NULL DEFAULT 0,\n CONSTRAINT \"FK_Passwords_Credentials_CredentialId\" FOREIGN KEY (\"CredentialId\") REFERENCES \"Credentials\" (\"Id\") ON DELETE CASCADE\n);\n\nCREATE TABLE \"TotpCodes\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_TotpCodes\" PRIMARY KEY,\n \"Name\" TEXT NOT NULL,\n \"SecretKey\" TEXT NOT NULL,\n \"CredentialId\" TEXT NOT NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"UpdatedAt\" TEXT NOT NULL,\n \"IsDeleted\" INTEGER NOT NULL DEFAULT 0,\n CONSTRAINT \"FK_TotpCodes_Credentials_CredentialId\" FOREIGN KEY (\"CredentialId\") REFERENCES \"Credentials\" (\"Id\") ON DELETE CASCADE\n);\n\n\n-- Restore data from temp tables\nINSERT INTO \"__EFMigrationsHistory\" SELECT * FROM \"__EFMigrationsHistory_temp\";\nINSERT INTO \"Aliases\" SELECT * FROM \"Aliases_temp\";\nINSERT INTO \"Services\" SELECT * FROM \"Services_temp\";\nINSERT INTO \"EncryptionKeys\" SELECT * FROM \"EncryptionKeys_temp\";\nINSERT INTO \"Settings\" SELECT * FROM \"Settings_temp\";\nINSERT INTO \"Credentials\" SELECT * FROM \"Credentials_temp\";\nINSERT INTO \"Attachments\" SELECT * FROM \"Attachments_temp\";\nINSERT INTO \"Passwords\" SELECT * FROM \"Passwords_temp\";\nINSERT INTO \"TotpCodes\" SELECT * FROM \"TotpCodes_temp\";\n\n-- =====================================================================================\n-- Date Format Normalization Migration\n-- =====================================================================================\n-- This migration normalizes ALL date fields to the standard format: 'yyyy-MM-dd HH:mm:ss.fff'\n-- Previously the different clients used different date formats which complicate date parsing.\n-- From version 0.24.0 onwards, all new dates are stored in this standard format.\n\n-- Update Aliases table (CreatedAt, UpdatedAt, BirthDate)\nUPDATE \"Aliases\" SET \"CreatedAt\" =\n CASE\n -- Already in correct format (yyyy-MM-dd HH:mm:ss.fff) - no change\n WHEN \"CreatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9] [0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9][0-9][0-9]'\n THEN \"CreatedAt\"\n\n -- ISO 8601 with milliseconds (yyyy-MM-ddTHH:mm:ss.fffZ) -> Replace T with space, remove Z and everything after .fff\n WHEN \"CreatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]T[0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9]*'\n THEN substr(\"CreatedAt\", 1, 10) || ' ' || substr(\"CreatedAt\", 12, 12)\n\n -- Without milliseconds (yyyy-MM-dd HH:mm:ss or yyyy-MM-ddTHH:mm:ssZ) -> Add .000\n WHEN \"CreatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9][T ][0-9][0-9]:[0-9][0-9]:[0-9][0-9]*'\n THEN substr(\"CreatedAt\", 1, 10) || ' ' || substr(replace(\"CreatedAt\", 'T', ' '), 12, 8) || '.000'\n\n -- Fallback: if none match, keep as-is (edge case)\n ELSE \"CreatedAt\"\n END;\n\nUPDATE \"Aliases\" SET \"UpdatedAt\" =\n CASE\n WHEN \"UpdatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9] [0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9][0-9][0-9]'\n THEN \"UpdatedAt\"\n WHEN \"UpdatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]T[0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9]*'\n THEN substr(\"UpdatedAt\", 1, 10) || ' ' || substr(\"UpdatedAt\", 12, 12)\n WHEN \"UpdatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9][T ][0-9][0-9]:[0-9][0-9]:[0-9][0-9]*'\n THEN substr(\"UpdatedAt\", 1, 10) || ' ' || substr(replace(\"UpdatedAt\", 'T', ' '), 12, 8) || '.000'\n ELSE \"UpdatedAt\"\n END;\n\n-- BirthDate: Always set time to 00:00:00 (no milliseconds for birth dates)\nUPDATE \"Aliases\" SET \"BirthDate\" =\n CASE\n -- If empty or already '0001-01-01 00:00:00', keep as-is\n WHEN \"BirthDate\" = '' OR \"BirthDate\" = '0001-01-01 00:00:00'\n THEN \"BirthDate\"\n\n -- If already in correct format (yyyy-MM-dd 00:00:00), keep as-is\n WHEN \"BirthDate\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9] 00:00:00'\n THEN \"BirthDate\"\n\n -- Extract date part and set time to 00:00:00\n WHEN \"BirthDate\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]*'\n THEN substr(\"BirthDate\", 1, 10) || ' 00:00:00'\n\n -- Fallback\n ELSE \"BirthDate\"\n END;\n\n-- Update Services table (CreatedAt, UpdatedAt)\nUPDATE \"Services\" SET \"CreatedAt\" =\n CASE\n WHEN \"CreatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9] [0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9][0-9][0-9]'\n THEN \"CreatedAt\"\n WHEN \"CreatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]T[0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9]*'\n THEN substr(\"CreatedAt\", 1, 10) || ' ' || substr(\"CreatedAt\", 12, 12)\n WHEN \"CreatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9][T ][0-9][0-9]:[0-9][0-9]:[0-9][0-9]*'\n THEN substr(\"CreatedAt\", 1, 10) || ' ' || substr(replace(\"CreatedAt\", 'T', ' '), 12, 8) || '.000'\n ELSE \"CreatedAt\"\n END;\n\nUPDATE \"Services\" SET \"UpdatedAt\" =\n CASE\n WHEN \"UpdatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9] [0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9][0-9][0-9]'\n THEN \"UpdatedAt\"\n WHEN \"UpdatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]T[0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9]*'\n THEN substr(\"UpdatedAt\", 1, 10) || ' ' || substr(\"UpdatedAt\", 12, 12)\n WHEN \"UpdatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9][T ][0-9][0-9]:[0-9][0-9]:[0-9][0-9]*'\n THEN substr(\"UpdatedAt\", 1, 10) || ' ' || substr(replace(\"UpdatedAt\", 'T', ' '), 12, 8) || '.000'\n ELSE \"UpdatedAt\"\n END;\n\n-- Update EncryptionKeys table (CreatedAt, UpdatedAt)\nUPDATE \"EncryptionKeys\" SET \"CreatedAt\" =\n CASE\n WHEN \"CreatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9] [0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9][0-9][0-9]'\n THEN \"CreatedAt\"\n WHEN \"CreatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]T[0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9]*'\n THEN substr(\"CreatedAt\", 1, 10) || ' ' || substr(\"CreatedAt\", 12, 12)\n WHEN \"CreatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9][T ][0-9][0-9]:[0-9][0-9]:[0-9][0-9]*'\n THEN substr(\"CreatedAt\", 1, 10) || ' ' || substr(replace(\"CreatedAt\", 'T', ' '), 12, 8) || '.000'\n ELSE \"CreatedAt\"\n END;\n\nUPDATE \"EncryptionKeys\" SET \"UpdatedAt\" =\n CASE\n WHEN \"UpdatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9] [0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9][0-9][0-9]'\n THEN \"UpdatedAt\"\n WHEN \"UpdatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]T[0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9]*'\n THEN substr(\"UpdatedAt\", 1, 10) || ' ' || substr(\"UpdatedAt\", 12, 12)\n WHEN \"UpdatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9][T ][0-9][0-9]:[0-9][0-9]:[0-9][0-9]*'\n THEN substr(\"UpdatedAt\", 1, 10) || ' ' || substr(replace(\"UpdatedAt\", 'T', ' '), 12, 8) || '.000'\n ELSE \"UpdatedAt\"\n END;\n\n-- Update Settings table (CreatedAt, UpdatedAt)\nUPDATE \"Settings\" SET \"CreatedAt\" =\n CASE\n WHEN \"CreatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9] [0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9][0-9][0-9]'\n THEN \"CreatedAt\"\n WHEN \"CreatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]T[0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9]*'\n THEN substr(\"CreatedAt\", 1, 10) || ' ' || substr(\"CreatedAt\", 12, 12)\n WHEN \"CreatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9][T ][0-9][0-9]:[0-9][0-9]:[0-9][0-9]*'\n THEN substr(\"CreatedAt\", 1, 10) || ' ' || substr(replace(\"CreatedAt\", 'T', ' '), 12, 8) || '.000'\n ELSE \"CreatedAt\"\n END;\n\nUPDATE \"Settings\" SET \"UpdatedAt\" =\n CASE\n WHEN \"UpdatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9] [0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9][0-9][0-9]'\n THEN \"UpdatedAt\"\n WHEN \"UpdatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]T[0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9]*'\n THEN substr(\"UpdatedAt\", 1, 10) || ' ' || substr(\"UpdatedAt\", 12, 12)\n WHEN \"UpdatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9][T ][0-9][0-9]:[0-9][0-9]:[0-9][0-9]*'\n THEN substr(\"UpdatedAt\", 1, 10) || ' ' || substr(replace(\"UpdatedAt\", 'T', ' '), 12, 8) || '.000'\n ELSE \"UpdatedAt\"\n END;\n\n-- Update Credentials table (CreatedAt, UpdatedAt)\nUPDATE \"Credentials\" SET \"CreatedAt\" =\n CASE\n WHEN \"CreatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9] [0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9][0-9][0-9]'\n THEN \"CreatedAt\"\n WHEN \"CreatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]T[0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9]*'\n THEN substr(\"CreatedAt\", 1, 10) || ' ' || substr(\"CreatedAt\", 12, 12)\n WHEN \"CreatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9][T ][0-9][0-9]:[0-9][0-9]:[0-9][0-9]*'\n THEN substr(\"CreatedAt\", 1, 10) || ' ' || substr(replace(\"CreatedAt\", 'T', ' '), 12, 8) || '.000'\n ELSE \"CreatedAt\"\n END;\n\nUPDATE \"Credentials\" SET \"UpdatedAt\" =\n CASE\n WHEN \"UpdatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9] [0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9][0-9][0-9]'\n THEN \"UpdatedAt\"\n WHEN \"UpdatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]T[0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9]*'\n THEN substr(\"UpdatedAt\", 1, 10) || ' ' || substr(\"UpdatedAt\", 12, 12)\n WHEN \"UpdatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9][T ][0-9][0-9]:[0-9][0-9]:[0-9][0-9]*'\n THEN substr(\"UpdatedAt\", 1, 10) || ' ' || substr(replace(\"UpdatedAt\", 'T', ' '), 12, 8) || '.000'\n ELSE \"UpdatedAt\"\n END;\n\n-- Update Attachments table (CreatedAt, UpdatedAt)\nUPDATE \"Attachments\" SET \"CreatedAt\" =\n CASE\n WHEN \"CreatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9] [0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9][0-9][0-9]'\n THEN \"CreatedAt\"\n WHEN \"CreatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]T[0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9]*'\n THEN substr(\"CreatedAt\", 1, 10) || ' ' || substr(\"CreatedAt\", 12, 12)\n WHEN \"CreatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9][T ][0-9][0-9]:[0-9][0-9]:[0-9][0-9]*'\n THEN substr(\"CreatedAt\", 1, 10) || ' ' || substr(replace(\"CreatedAt\", 'T', ' '), 12, 8) || '.000'\n ELSE \"CreatedAt\"\n END;\n\nUPDATE \"Attachments\" SET \"UpdatedAt\" =\n CASE\n WHEN \"UpdatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9] [0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9][0-9][0-9]'\n THEN \"UpdatedAt\"\n WHEN \"UpdatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]T[0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9]*'\n THEN substr(\"UpdatedAt\", 1, 10) || ' ' || substr(\"UpdatedAt\", 12, 12)\n WHEN \"UpdatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9][T ][0-9][0-9]:[0-9][0-9]:[0-9][0-9]*'\n THEN substr(\"UpdatedAt\", 1, 10) || ' ' || substr(replace(\"UpdatedAt\", 'T', ' '), 12, 8) || '.000'\n ELSE \"UpdatedAt\"\n END;\n\n-- Update Passwords table (CreatedAt, UpdatedAt)\nUPDATE \"Passwords\" SET \"CreatedAt\" =\n CASE\n WHEN \"CreatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9] [0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9][0-9][0-9]'\n THEN \"CreatedAt\"\n WHEN \"CreatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]T[0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9]*'\n THEN substr(\"CreatedAt\", 1, 10) || ' ' || substr(\"CreatedAt\", 12, 12)\n WHEN \"CreatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9][T ][0-9][0-9]:[0-9][0-9]:[0-9][0-9]*'\n THEN substr(\"CreatedAt\", 1, 10) || ' ' || substr(replace(\"CreatedAt\", 'T', ' '), 12, 8) || '.000'\n ELSE \"CreatedAt\"\n END;\n\nUPDATE \"Passwords\" SET \"UpdatedAt\" =\n CASE\n WHEN \"UpdatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9] [0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9][0-9][0-9]'\n THEN \"UpdatedAt\"\n WHEN \"UpdatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]T[0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9]*'\n THEN substr(\"UpdatedAt\", 1, 10) || ' ' || substr(\"UpdatedAt\", 12, 12)\n WHEN \"UpdatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9][T ][0-9][0-9]:[0-9][0-9]:[0-9][0-9]*'\n THEN substr(\"UpdatedAt\", 1, 10) || ' ' || substr(replace(\"UpdatedAt\", 'T', ' '), 12, 8) || '.000'\n ELSE \"UpdatedAt\"\n END;\n\n-- Update TotpCodes table (CreatedAt, UpdatedAt)\nUPDATE \"TotpCodes\" SET \"CreatedAt\" =\n CASE\n WHEN \"CreatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9] [0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9][0-9][0-9]'\n THEN \"CreatedAt\"\n WHEN \"CreatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]T[0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9]*'\n THEN substr(\"CreatedAt\", 1, 10) || ' ' || substr(\"CreatedAt\", 12, 12)\n WHEN \"CreatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9][T ][0-9][0-9]:[0-9][0-9]:[0-9][0-9]*'\n THEN substr(\"CreatedAt\", 1, 10) || ' ' || substr(replace(\"CreatedAt\", 'T', ' '), 12, 8) || '.000'\n ELSE \"CreatedAt\"\n END;\n\nUPDATE \"TotpCodes\" SET \"UpdatedAt\" =\n CASE\n WHEN \"UpdatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9] [0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9][0-9][0-9]'\n THEN \"UpdatedAt\"\n WHEN \"UpdatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]T[0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9]*'\n THEN substr(\"UpdatedAt\", 1, 10) || ' ' || substr(\"UpdatedAt\", 12, 12)\n WHEN \"UpdatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9][T ][0-9][0-9]:[0-9][0-9]:[0-9][0-9]*'\n THEN substr(\"UpdatedAt\", 1, 10) || ' ' || substr(replace(\"UpdatedAt\", 'T', ' '), 12, 8) || '.000'\n ELSE \"UpdatedAt\"\n END;\n\n-- =====================================================================================\n-- End of Date Format Normalization Migration\n-- =====================================================================================\n\n-- Recreate indexes\nCREATE INDEX \"IX_Credentials_AliasId\" ON \"Credentials\" (\"AliasId\");\nCREATE INDEX \"IX_Credentials_ServiceId\" ON \"Credentials\" (\"ServiceId\");\nCREATE INDEX \"IX_Attachments_CredentialId\" ON \"Attachments\" (\"CredentialId\");\nCREATE INDEX \"IX_Passwords_CredentialId\" ON \"Passwords\" (\"CredentialId\");\nCREATE INDEX \"IX_TotpCodes_CredentialId\" ON \"TotpCodes\" (\"CredentialId\");\n\n-- Clean up temp tables\nDROP TABLE \"__EFMigrationsHistory_temp\";\nDROP TABLE \"Aliases_temp\";\nDROP TABLE \"Services_temp\";\nDROP TABLE \"EncryptionKeys_temp\";\nDROP TABLE \"Settings_temp\";\nDROP TABLE \"Credentials_temp\";\nDROP TABLE \"Attachments_temp\";\nDROP TABLE \"Passwords_temp\";\nDROP TABLE \"TotpCodes_temp\";\n\nPRAGMA foreign_keys = ON;\n\n\nCREATE TABLE \"Passkeys\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_Passkeys\" PRIMARY KEY,\n \"RpId\" TEXT COLLATE NOCASE NOT NULL,\n \"UserHandle\" BLOB NOT NULL,\n \"PublicKey\" TEXT NOT NULL,\n \"PrivateKey\" TEXT NOT NULL,\n \"PrfKey\" BLOB NULL,\n \"DisplayName\" TEXT NOT NULL,\n \"AdditionalData\" BLOB NULL,\n \"CredentialId\" TEXT NOT NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"UpdatedAt\" TEXT NOT NULL,\n \"IsDeleted\" INTEGER NOT NULL,\n CONSTRAINT \"FK_Passkeys_Credentials_CredentialId\" FOREIGN KEY (\"CredentialId\") REFERENCES \"Credentials\" (\"Id\") ON DELETE CASCADE\n);\n\nCREATE INDEX \"IX_Passkeys_CredentialId\" ON \"Passkeys\" (\"CredentialId\");\n\nCREATE INDEX \"IX_Passkeys_RpId\" ON \"Passkeys\" (\"RpId\");\n\nINSERT INTO \"__EFMigrationsHistory\" (\"MigrationId\", \"ProductVersion\")\nVALUES ('20251014122838_1.6.0-AddPasskeys', '9.0.4');\n\nALTER TABLE \"TotpCodes\" RENAME COLUMN \"CredentialId\" TO \"ItemId\";\n\nDROP INDEX IF EXISTS \"IX_TotpCodes_CredentialId\";\n\nCREATE INDEX IF NOT EXISTS \"IX_TotpCodes_ItemId\" ON \"TotpCodes\" (\"ItemId\");\n\nALTER TABLE \"Passkeys\" RENAME COLUMN \"CredentialId\" TO \"ItemId\";\n\nDROP INDEX IF EXISTS \"IX_Passkeys_CredentialId\";\n\nCREATE INDEX IF NOT EXISTS \"IX_Passkeys_ItemId\" ON \"Passkeys\" (\"ItemId\");\n\nALTER TABLE \"Attachments\" RENAME COLUMN \"CredentialId\" TO \"ItemId\";\n\nDROP INDEX IF EXISTS \"IX_Attachments_CredentialId\";\n\nCREATE INDEX IF NOT EXISTS \"IX_Attachments_ItemId\" ON \"Attachments\" (\"ItemId\");\n\nCREATE TABLE \"FieldDefinitions\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_FieldDefinitions\" PRIMARY KEY,\n \"FieldType\" TEXT NOT NULL,\n \"Label\" TEXT NOT NULL,\n \"IsMultiValue\" INTEGER NOT NULL,\n \"IsHidden\" INTEGER NOT NULL,\n \"EnableHistory\" INTEGER NOT NULL,\n \"Weight\" INTEGER NOT NULL,\n \"ApplicableToTypes\" TEXT NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"UpdatedAt\" TEXT NOT NULL,\n \"IsDeleted\" INTEGER NOT NULL\n);\n\nCREATE TABLE \"Folders\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_Folders\" PRIMARY KEY,\n \"Name\" TEXT NOT NULL,\n \"ParentFolderId\" TEXT NULL,\n \"Weight\" INTEGER NOT NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"UpdatedAt\" TEXT NOT NULL,\n \"IsDeleted\" INTEGER NOT NULL,\n CONSTRAINT \"FK_Folders_Folders_ParentFolderId\" FOREIGN KEY (\"ParentFolderId\") REFERENCES \"Folders\" (\"Id\") ON DELETE CASCADE\n);\n\nCREATE TABLE \"Logos\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_Logos\" PRIMARY KEY,\n \"Source\" TEXT NOT NULL,\n \"FileData\" BLOB NULL,\n \"MimeType\" TEXT NULL,\n \"FetchedAt\" TEXT NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"UpdatedAt\" TEXT NOT NULL,\n \"IsDeleted\" INTEGER NOT NULL\n);\n\nCREATE TABLE \"Tags\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_Tags\" PRIMARY KEY,\n \"Name\" TEXT NOT NULL,\n \"Color\" TEXT NULL,\n \"DisplayOrder\" INTEGER NOT NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"UpdatedAt\" TEXT NOT NULL,\n \"IsDeleted\" INTEGER NOT NULL\n);\n\nCREATE TABLE \"Items\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_Items\" PRIMARY KEY,\n \"Name\" TEXT NULL,\n \"ItemType\" TEXT NOT NULL,\n \"LogoId\" TEXT NULL,\n \"DeletedAt\" TEXT NULL,\n \"FolderId\" TEXT NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"UpdatedAt\" TEXT NOT NULL,\n \"IsDeleted\" INTEGER NOT NULL,\n CONSTRAINT \"FK_Items_Folders_FolderId\" FOREIGN KEY (\"FolderId\") REFERENCES \"Folders\" (\"Id\") ON DELETE SET NULL,\n CONSTRAINT \"FK_Items_Logos_LogoId\" FOREIGN KEY (\"LogoId\") REFERENCES \"Logos\" (\"Id\") ON DELETE SET NULL\n);\n\nCREATE TABLE \"FieldHistories\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_FieldHistories\" PRIMARY KEY,\n \"ItemId\" TEXT NOT NULL,\n \"FieldDefinitionId\" TEXT NULL,\n \"FieldKey\" TEXT NULL,\n \"ValueSnapshot\" TEXT NOT NULL,\n \"ChangedAt\" TEXT NOT NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"UpdatedAt\" TEXT NOT NULL,\n \"IsDeleted\" INTEGER NOT NULL,\n CONSTRAINT \"FK_FieldHistories_FieldDefinitions_FieldDefinitionId\" FOREIGN KEY (\"FieldDefinitionId\") REFERENCES \"FieldDefinitions\" (\"Id\") ON DELETE CASCADE,\n CONSTRAINT \"FK_FieldHistories_Items_ItemId\" FOREIGN KEY (\"ItemId\") REFERENCES \"Items\" (\"Id\") ON DELETE CASCADE\n);\n\nCREATE TABLE \"FieldValues\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_FieldValues\" PRIMARY KEY,\n \"ItemId\" TEXT NOT NULL,\n \"FieldDefinitionId\" TEXT NULL,\n \"FieldKey\" TEXT NULL,\n \"Value\" TEXT NULL,\n \"Weight\" INTEGER NOT NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"UpdatedAt\" TEXT NOT NULL,\n \"IsDeleted\" INTEGER NOT NULL,\n CONSTRAINT \"FK_FieldValues_FieldDefinitions_FieldDefinitionId\" FOREIGN KEY (\"FieldDefinitionId\") REFERENCES \"FieldDefinitions\" (\"Id\") ON DELETE CASCADE,\n CONSTRAINT \"FK_FieldValues_Items_ItemId\" FOREIGN KEY (\"ItemId\") REFERENCES \"Items\" (\"Id\") ON DELETE CASCADE\n);\n\nCREATE TABLE \"ItemTags\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_ItemTags\" PRIMARY KEY,\n \"ItemId\" TEXT NOT NULL,\n \"TagId\" TEXT NOT NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"UpdatedAt\" TEXT NOT NULL,\n \"IsDeleted\" INTEGER NOT NULL,\n CONSTRAINT \"FK_ItemTags_Items_ItemId\" FOREIGN KEY (\"ItemId\") REFERENCES \"Items\" (\"Id\") ON DELETE CASCADE,\n CONSTRAINT \"FK_ItemTags_Tags_TagId\" FOREIGN KEY (\"TagId\") REFERENCES \"Tags\" (\"Id\") ON DELETE CASCADE\n);\n\nCREATE INDEX \"IX_FieldHistories_FieldDefinitionId\" ON \"FieldHistories\" (\"FieldDefinitionId\");\n\nCREATE INDEX \"IX_FieldHistories_ItemId\" ON \"FieldHistories\" (\"ItemId\");\n\nCREATE INDEX \"IX_FieldValues_FieldDefinitionId\" ON \"FieldValues\" (\"FieldDefinitionId\");\n\nCREATE INDEX \"IX_FieldValues_FieldKey\" ON \"FieldValues\" (\"FieldKey\");\n\nCREATE INDEX \"IX_FieldValues_ItemId\" ON \"FieldValues\" (\"ItemId\");\n\nCREATE INDEX \"IX_FieldValues_ItemId_FieldDefinitionId_Weight\" ON \"FieldValues\" (\"ItemId\", \"FieldDefinitionId\", \"Weight\");\n\nCREATE INDEX \"IX_FieldValues_ItemId_FieldKey\" ON \"FieldValues\" (\"ItemId\", \"FieldKey\");\n\nCREATE INDEX \"IX_Folders_ParentFolderId\" ON \"Folders\" (\"ParentFolderId\");\n\nCREATE INDEX \"IX_Items_FolderId\" ON \"Items\" (\"FolderId\");\n\nCREATE INDEX \"IX_Items_LogoId\" ON \"Items\" (\"LogoId\");\n\nCREATE INDEX \"IX_ItemTags_ItemId\" ON \"ItemTags\" (\"ItemId\");\n\nCREATE UNIQUE INDEX \"IX_ItemTags_ItemId_TagId\" ON \"ItemTags\" (\"ItemId\", \"TagId\");\n\nCREATE INDEX \"IX_ItemTags_TagId\" ON \"ItemTags\" (\"TagId\");\n\nCREATE UNIQUE INDEX \"IX_Logos_Source\" ON \"Logos\" (\"Source\");\n\nCREATE INDEX \"IX_Tags_Name\" ON \"Tags\" (\"Name\");\n\n\n INSERT INTO Items (Id, Name, ItemType, LogoId, FolderId, CreatedAt, UpdatedAt, IsDeleted)\n SELECT\n c.Id,\n s.Name AS Name,\n CASE\n WHEN a.Id IS NOT NULL AND (\n (a.FirstName IS NOT NULL AND a.FirstName != '') OR\n (a.LastName IS NOT NULL AND a.LastName != '') OR\n (a.Gender IS NOT NULL AND a.Gender != '') OR\n (a.BirthDate IS NOT NULL AND a.BirthDate != '' AND a.BirthDate NOT LIKE '0001-%')\n ) THEN 'Alias'\n ELSE 'Login'\n END AS ItemType,\n NULL AS LogoId,\n NULL AS FolderId,\n c.CreatedAt,\n c.UpdatedAt,\n c.IsDeleted\n FROM Credentials c\n LEFT JOIN Services s ON s.Id = c.ServiceId\n LEFT JOIN Aliases a ON a.Id = c.AliasId;\n \n\n\n INSERT INTO Logos (Id, Source, FileData, MimeType, FetchedAt, CreatedAt, UpdatedAt, IsDeleted)\n SELECT\n UPPER(SUBSTR(hex(randomblob(4)), 1, 8) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(6)), 1, 12)) AS Id,\n -- Extract and normalize hostname: remove protocol, path, lowercase, and www. prefix\n REPLACE(\n LOWER(\n SUBSTR(\n CASE\n WHEN s.Url LIKE 'https://%' THEN SUBSTR(s.Url, 9)\n WHEN s.Url LIKE 'http://%' THEN SUBSTR(s.Url, 8)\n ELSE s.Url\n END,\n 1,\n CASE\n WHEN INSTR(\n CASE\n WHEN s.Url LIKE 'https://%' THEN SUBSTR(s.Url, 9)\n WHEN s.Url LIKE 'http://%' THEN SUBSTR(s.Url, 8)\n ELSE s.Url\n END, '/') > 0\n THEN INSTR(\n CASE\n WHEN s.Url LIKE 'https://%' THEN SUBSTR(s.Url, 9)\n WHEN s.Url LIKE 'http://%' THEN SUBSTR(s.Url, 8)\n ELSE s.Url\n END, '/') - 1\n ELSE LENGTH(\n CASE\n WHEN s.Url LIKE 'https://%' THEN SUBSTR(s.Url, 9)\n WHEN s.Url LIKE 'http://%' THEN SUBSTR(s.Url, 8)\n ELSE s.Url\n END)\n END\n )\n ),\n 'www.', ''\n ) AS Source,\n s.Logo AS FileData,\n 'image/png' AS MimeType,\n NULL AS FetchedAt,\n MIN(s.CreatedAt) AS CreatedAt,\n MAX(s.UpdatedAt) AS UpdatedAt,\n 0 AS IsDeleted\n FROM Services s\n WHERE s.Logo IS NOT NULL AND s.Url IS NOT NULL AND s.Url != ''\n GROUP BY REPLACE(\n LOWER(\n SUBSTR(\n CASE\n WHEN s.Url LIKE 'https://%' THEN SUBSTR(s.Url, 9)\n WHEN s.Url LIKE 'http://%' THEN SUBSTR(s.Url, 8)\n ELSE s.Url\n END,\n 1,\n CASE\n WHEN INSTR(\n CASE\n WHEN s.Url LIKE 'https://%' THEN SUBSTR(s.Url, 9)\n WHEN s.Url LIKE 'http://%' THEN SUBSTR(s.Url, 8)\n ELSE s.Url\n END, '/') > 0\n THEN INSTR(\n CASE\n WHEN s.Url LIKE 'https://%' THEN SUBSTR(s.Url, 9)\n WHEN s.Url LIKE 'http://%' THEN SUBSTR(s.Url, 8)\n ELSE s.Url\n END, '/') - 1\n ELSE LENGTH(\n CASE\n WHEN s.Url LIKE 'https://%' THEN SUBSTR(s.Url, 9)\n WHEN s.Url LIKE 'http://%' THEN SUBSTR(s.Url, 8)\n ELSE s.Url\n END)\n END\n )\n ),\n 'www.', ''\n );\n \n\n\n UPDATE Items\n SET LogoId = (\n SELECT l.Id FROM Logos l\n INNER JOIN Services s ON REPLACE(\n LOWER(\n SUBSTR(\n CASE\n WHEN s.Url LIKE 'https://%' THEN SUBSTR(s.Url, 9)\n WHEN s.Url LIKE 'http://%' THEN SUBSTR(s.Url, 8)\n ELSE s.Url\n END,\n 1,\n CASE\n WHEN INSTR(\n CASE\n WHEN s.Url LIKE 'https://%' THEN SUBSTR(s.Url, 9)\n WHEN s.Url LIKE 'http://%' THEN SUBSTR(s.Url, 8)\n ELSE s.Url\n END, '/') > 0\n THEN INSTR(\n CASE\n WHEN s.Url LIKE 'https://%' THEN SUBSTR(s.Url, 9)\n WHEN s.Url LIKE 'http://%' THEN SUBSTR(s.Url, 8)\n ELSE s.Url\n END, '/') - 1\n ELSE LENGTH(\n CASE\n WHEN s.Url LIKE 'https://%' THEN SUBSTR(s.Url, 9)\n WHEN s.Url LIKE 'http://%' THEN SUBSTR(s.Url, 8)\n ELSE s.Url\n END)\n END\n )\n ),\n 'www.', ''\n ) = l.Source\n INNER JOIN Credentials c ON c.ServiceId = s.Id\n WHERE c.Id = Items.Id\n LIMIT 1\n )\n WHERE EXISTS (\n SELECT 1 FROM Credentials c\n INNER JOIN Services s ON s.Id = c.ServiceId\n WHERE c.Id = Items.Id AND s.Logo IS NOT NULL\n );\n \n\n\n INSERT INTO FieldValues (Id, ItemId, FieldDefinitionId, FieldKey, Value, Weight, CreatedAt, UpdatedAt, IsDeleted)\n SELECT\n UPPER(SUBSTR(hex(randomblob(4)), 1, 8) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(6)), 1, 12)) AS Id,\n c.Id AS ItemId,\n NULL AS FieldDefinitionId,\n 'login.url' AS FieldKey,\n s.Url AS Value,\n 0 AS Weight,\n s.UpdatedAt AS CreatedAt,\n s.UpdatedAt AS UpdatedAt,\n 0 AS IsDeleted\n FROM Credentials c\n INNER JOIN Services s ON s.Id = c.ServiceId\n WHERE s.Url IS NOT NULL AND s.Url != '';\n \n\n\n INSERT INTO FieldValues (Id, ItemId, FieldDefinitionId, FieldKey, Value, Weight, CreatedAt, UpdatedAt, IsDeleted)\n SELECT\n UPPER(SUBSTR(hex(randomblob(4)), 1, 8) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(6)), 1, 12)) AS Id,\n c.Id AS ItemId,\n NULL AS FieldDefinitionId,\n 'login.username' AS FieldKey,\n c.Username AS Value,\n 0 AS Weight,\n c.UpdatedAt AS CreatedAt,\n c.UpdatedAt AS UpdatedAt,\n 0 AS IsDeleted\n FROM Credentials c\n WHERE c.Username IS NOT NULL AND c.Username != '';\n \n\n\n INSERT INTO FieldValues (Id, ItemId, FieldDefinitionId, FieldKey, Value, Weight, CreatedAt, UpdatedAt, IsDeleted)\n SELECT\n UPPER(SUBSTR(hex(randomblob(4)), 1, 8) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(6)), 1, 12)) AS Id,\n c.Id AS ItemId,\n NULL AS FieldDefinitionId,\n 'login.notes' AS FieldKey,\n c.Notes AS Value,\n 0 AS Weight,\n c.UpdatedAt AS CreatedAt,\n c.UpdatedAt AS UpdatedAt,\n 0 AS IsDeleted\n FROM Credentials c\n WHERE c.Notes IS NOT NULL AND c.Notes != '';\n \n\n\n INSERT INTO FieldValues (Id, ItemId, FieldDefinitionId, FieldKey, Value, Weight, CreatedAt, UpdatedAt, IsDeleted)\n SELECT\n UPPER(SUBSTR(hex(randomblob(4)), 1, 8) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(6)), 1, 12)) AS Id,\n p.CredentialId AS ItemId,\n NULL AS FieldDefinitionId,\n 'login.password' AS FieldKey,\n p.Value AS Value,\n 0 AS Weight,\n p.UpdatedAt AS CreatedAt,\n p.UpdatedAt AS UpdatedAt,\n 0 AS IsDeleted\n FROM Passwords p\n INNER JOIN (\n SELECT CredentialId, MAX(UpdatedAt) AS MaxUpdated, MAX(Id) AS MaxId\n FROM Passwords\n WHERE IsDeleted = 0\n GROUP BY CredentialId\n ) pm ON p.CredentialId = pm.CredentialId AND p.UpdatedAt = pm.MaxUpdated AND p.Id = pm.MaxId\n WHERE p.IsDeleted = 0;\n \n\n\n INSERT INTO FieldValues (Id, ItemId, FieldDefinitionId, FieldKey, Value, Weight, CreatedAt, UpdatedAt, IsDeleted)\n SELECT\n UPPER(SUBSTR(hex(randomblob(4)), 1, 8) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(6)), 1, 12)) AS Id,\n c.Id AS ItemId,\n NULL AS FieldDefinitionId,\n 'login.email' AS FieldKey,\n a.Email AS Value,\n 0 AS Weight,\n a.UpdatedAt AS CreatedAt,\n a.UpdatedAt AS UpdatedAt,\n 0 AS IsDeleted\n FROM Credentials c\n INNER JOIN Aliases a ON a.Id = c.AliasId\n WHERE a.Email IS NOT NULL AND a.Email != '';\n \n\n\n INSERT INTO FieldValues (Id, ItemId, FieldDefinitionId, FieldKey, Value, Weight, CreatedAt, UpdatedAt, IsDeleted)\n SELECT\n UPPER(SUBSTR(hex(randomblob(4)), 1, 8) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(6)), 1, 12)) AS Id,\n c.Id AS ItemId,\n NULL AS FieldDefinitionId,\n 'alias.first_name' AS FieldKey,\n a.FirstName AS Value,\n 0 AS Weight,\n a.UpdatedAt AS CreatedAt,\n a.UpdatedAt AS UpdatedAt,\n 0 AS IsDeleted\n FROM Credentials c\n INNER JOIN Aliases a ON a.Id = c.AliasId\n WHERE a.FirstName IS NOT NULL AND a.FirstName != '';\n \n\n\n INSERT INTO FieldValues (Id, ItemId, FieldDefinitionId, FieldKey, Value, Weight, CreatedAt, UpdatedAt, IsDeleted)\n SELECT\n UPPER(SUBSTR(hex(randomblob(4)), 1, 8) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(6)), 1, 12)) AS Id,\n c.Id AS ItemId,\n NULL AS FieldDefinitionId,\n 'alias.last_name' AS FieldKey,\n a.LastName AS Value,\n 0 AS Weight,\n a.UpdatedAt AS CreatedAt,\n a.UpdatedAt AS UpdatedAt,\n 0 AS IsDeleted\n FROM Credentials c\n INNER JOIN Aliases a ON a.Id = c.AliasId\n WHERE a.LastName IS NOT NULL AND a.LastName != '';\n \n\n\n INSERT INTO FieldValues (Id, ItemId, FieldDefinitionId, FieldKey, Value, Weight, CreatedAt, UpdatedAt, IsDeleted)\n SELECT\n UPPER(SUBSTR(hex(randomblob(4)), 1, 8) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(6)), 1, 12)) AS Id,\n c.Id AS ItemId,\n NULL AS FieldDefinitionId,\n 'alias.gender' AS FieldKey,\n a.Gender AS Value,\n 0 AS Weight,\n a.UpdatedAt AS CreatedAt,\n a.UpdatedAt AS UpdatedAt,\n 0 AS IsDeleted\n FROM Credentials c\n INNER JOIN Aliases a ON a.Id = c.AliasId\n WHERE a.Gender IS NOT NULL AND a.Gender != '';\n \n\n\n INSERT INTO FieldValues (Id, ItemId, FieldDefinitionId, FieldKey, Value, Weight, CreatedAt, UpdatedAt, IsDeleted)\n SELECT\n UPPER(SUBSTR(hex(randomblob(4)), 1, 8) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(6)), 1, 12)) AS Id,\n c.Id AS ItemId,\n NULL AS FieldDefinitionId,\n 'alias.birthdate' AS FieldKey,\n SUBSTR(a.BirthDate, 1, 10) AS Value,\n 0 AS Weight,\n a.UpdatedAt AS CreatedAt,\n a.UpdatedAt AS UpdatedAt,\n 0 AS IsDeleted\n FROM Credentials c\n INNER JOIN Aliases a ON a.Id = c.AliasId\n WHERE a.BirthDate IS NOT NULL AND a.BirthDate != '' AND a.BirthDate NOT LIKE '0001-%';\n \n\nDROP TABLE \"Passwords\";\n\nDROP TABLE \"Credentials\";\n\nDROP TABLE \"Aliases\";\n\nDROP TABLE \"Services\";\n\nCREATE TABLE \"ef_temp_Attachments\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_Attachments\" PRIMARY KEY,\n \"Blob\" BLOB NOT NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"Filename\" TEXT NOT NULL,\n \"IsDeleted\" INTEGER NOT NULL,\n \"ItemId\" TEXT NOT NULL,\n \"UpdatedAt\" TEXT NOT NULL,\n CONSTRAINT \"FK_Attachments_Items_ItemId\" FOREIGN KEY (\"ItemId\") REFERENCES \"Items\" (\"Id\") ON DELETE CASCADE\n);\n\nINSERT INTO \"ef_temp_Attachments\" (\"Id\", \"Blob\", \"CreatedAt\", \"Filename\", \"IsDeleted\", \"ItemId\", \"UpdatedAt\")\nSELECT \"Id\", \"Blob\", \"CreatedAt\", \"Filename\", \"IsDeleted\", \"ItemId\", \"UpdatedAt\"\nFROM \"Attachments\";\n\nCREATE TABLE \"ef_temp_Passkeys\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_Passkeys\" PRIMARY KEY,\n \"AdditionalData\" BLOB NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"DisplayName\" TEXT NOT NULL,\n \"IsDeleted\" INTEGER NOT NULL,\n \"ItemId\" TEXT NOT NULL,\n \"PrfKey\" BLOB NULL,\n \"PrivateKey\" TEXT NOT NULL,\n \"PublicKey\" TEXT NOT NULL,\n \"RpId\" TEXT COLLATE NOCASE NOT NULL,\n \"UpdatedAt\" TEXT NOT NULL,\n \"UserHandle\" BLOB NOT NULL,\n CONSTRAINT \"FK_Passkeys_Items_ItemId\" FOREIGN KEY (\"ItemId\") REFERENCES \"Items\" (\"Id\") ON DELETE CASCADE\n);\n\nINSERT INTO \"ef_temp_Passkeys\" (\"Id\", \"AdditionalData\", \"CreatedAt\", \"DisplayName\", \"IsDeleted\", \"ItemId\", \"PrfKey\", \"PrivateKey\", \"PublicKey\", \"RpId\", \"UpdatedAt\", \"UserHandle\")\nSELECT \"Id\", \"AdditionalData\", \"CreatedAt\", \"DisplayName\", \"IsDeleted\", \"ItemId\", \"PrfKey\", \"PrivateKey\", \"PublicKey\", \"RpId\", \"UpdatedAt\", \"UserHandle\"\nFROM \"Passkeys\";\n\nCREATE TABLE \"ef_temp_TotpCodes\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_TotpCodes\" PRIMARY KEY,\n \"CreatedAt\" TEXT NOT NULL,\n \"IsDeleted\" INTEGER NOT NULL,\n \"ItemId\" TEXT NOT NULL,\n \"Name\" TEXT NOT NULL,\n \"SecretKey\" TEXT NOT NULL,\n \"UpdatedAt\" TEXT NOT NULL,\n CONSTRAINT \"FK_TotpCodes_Items_ItemId\" FOREIGN KEY (\"ItemId\") REFERENCES \"Items\" (\"Id\") ON DELETE CASCADE\n);\n\nINSERT INTO \"ef_temp_TotpCodes\" (\"Id\", \"CreatedAt\", \"IsDeleted\", \"ItemId\", \"Name\", \"SecretKey\", \"UpdatedAt\")\nSELECT \"Id\", \"CreatedAt\", \"IsDeleted\", \"ItemId\", \"Name\", \"SecretKey\", \"UpdatedAt\"\nFROM \"TotpCodes\";\n\nCOMMIT;\n\nPRAGMA foreign_keys = 0;\n\nBEGIN TRANSACTION;\nDROP TABLE \"Attachments\";\n\nALTER TABLE \"ef_temp_Attachments\" RENAME TO \"Attachments\";\n\nDROP TABLE \"Passkeys\";\n\nALTER TABLE \"ef_temp_Passkeys\" RENAME TO \"Passkeys\";\n\nDROP TABLE \"TotpCodes\";\n\nALTER TABLE \"ef_temp_TotpCodes\" RENAME TO \"TotpCodes\";\n\nCOMMIT;\n\nPRAGMA foreign_keys = 1;\n\nBEGIN TRANSACTION;\nCREATE INDEX \"IX_Attachments_ItemId\" ON \"Attachments\" (\"ItemId\");\n\nCREATE INDEX \"IX_Passkeys_ItemId\" ON \"Passkeys\" (\"ItemId\");\n\nCREATE INDEX \"IX_Passkeys_RpId\" ON \"Passkeys\" (\"RpId\");\n\nCREATE INDEX \"IX_TotpCodes_ItemId\" ON \"TotpCodes\" (\"ItemId\");\n\nCOMMIT;\n\nINSERT INTO \"__EFMigrationsHistory\" (\"MigrationId\", \"ProductVersion\")\nVALUES ('20251213111207_1.7.0-FieldBasedDataModelUpdate', '9.0.4');\n"; +declare const COMPLETE_SCHEMA_SQL = "\n\uFEFFCREATE TABLE IF NOT EXISTS \"__EFMigrationsHistory\" (\n \"MigrationId\" TEXT NOT NULL CONSTRAINT \"PK___EFMigrationsHistory\" PRIMARY KEY,\n \"ProductVersion\" TEXT NOT NULL\n);\n\nBEGIN TRANSACTION;\nCREATE TABLE \"Aliases\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_Aliases\" PRIMARY KEY,\n \"Gender\" VARCHAR NULL,\n \"FirstName\" VARCHAR NULL,\n \"LastName\" VARCHAR NULL,\n \"NickName\" VARCHAR NULL,\n \"BirthDate\" TEXT NOT NULL,\n \"AddressStreet\" VARCHAR NULL,\n \"AddressCity\" VARCHAR NULL,\n \"AddressState\" VARCHAR NULL,\n \"AddressZipCode\" VARCHAR NULL,\n \"AddressCountry\" VARCHAR NULL,\n \"Hobbies\" TEXT NULL,\n \"EmailPrefix\" TEXT NULL,\n \"PhoneMobile\" TEXT NULL,\n \"BankAccountIBAN\" TEXT NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"UpdatedAt\" TEXT NOT NULL\n);\n\nCREATE TABLE \"Services\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_Services\" PRIMARY KEY,\n \"Name\" TEXT NULL,\n \"Url\" TEXT NULL,\n \"Logo\" BLOB NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"UpdatedAt\" TEXT NOT NULL\n);\n\nCREATE TABLE \"Credentials\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_Credentials\" PRIMARY KEY,\n \"AliasId\" TEXT NOT NULL,\n \"Notes\" TEXT NULL,\n \"Username\" TEXT NOT NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"UpdatedAt\" TEXT NOT NULL,\n \"ServiceId\" TEXT NOT NULL,\n CONSTRAINT \"FK_Credentials_Aliases_AliasId\" FOREIGN KEY (\"AliasId\") REFERENCES \"Aliases\" (\"Id\") ON DELETE CASCADE,\n CONSTRAINT \"FK_Credentials_Services_ServiceId\" FOREIGN KEY (\"ServiceId\") REFERENCES \"Services\" (\"Id\") ON DELETE CASCADE\n);\n\nCREATE TABLE \"Attachment\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_Attachment\" PRIMARY KEY,\n \"Filename\" TEXT NOT NULL,\n \"Blob\" BLOB NOT NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"UpdatedAt\" TEXT NOT NULL,\n \"CredentialId\" TEXT NOT NULL,\n CONSTRAINT \"FK_Attachment_Credentials_CredentialId\" FOREIGN KEY (\"CredentialId\") REFERENCES \"Credentials\" (\"Id\") ON DELETE CASCADE\n);\n\nCREATE TABLE \"Passwords\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_Passwords\" PRIMARY KEY,\n \"Value\" TEXT NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"UpdatedAt\" TEXT NOT NULL,\n \"CredentialId\" TEXT NOT NULL,\n CONSTRAINT \"FK_Passwords_Credentials_CredentialId\" FOREIGN KEY (\"CredentialId\") REFERENCES \"Credentials\" (\"Id\") ON DELETE CASCADE\n);\n\nCREATE INDEX \"IX_Attachment_CredentialId\" ON \"Attachment\" (\"CredentialId\");\n\nCREATE INDEX \"IX_Credentials_AliasId\" ON \"Credentials\" (\"AliasId\");\n\nCREATE INDEX \"IX_Credentials_ServiceId\" ON \"Credentials\" (\"ServiceId\");\n\nCREATE INDEX \"IX_Passwords_CredentialId\" ON \"Passwords\" (\"CredentialId\");\n\nINSERT INTO \"__EFMigrationsHistory\" (\"MigrationId\", \"ProductVersion\")\nVALUES ('20240708094944_1.0.0-InitialMigration', '9.0.4');\n\nINSERT INTO \"__EFMigrationsHistory\" (\"MigrationId\", \"ProductVersion\")\nVALUES ('20240708224522_1.0.1-EmptyTestMigration', '9.0.4');\n\nALTER TABLE \"Aliases\" RENAME COLUMN \"EmailPrefix\" TO \"Email\";\n\nINSERT INTO \"__EFMigrationsHistory\" (\"MigrationId\", \"ProductVersion\")\nVALUES ('20240711204207_1.0.2-ChangeEmailColumn', '9.0.4');\n\nCREATE TABLE \"EncryptionKeys\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_EncryptionKeys\" PRIMARY KEY,\n \"PublicKey\" TEXT NOT NULL,\n \"PrivateKey\" TEXT NOT NULL,\n \"IsPrimary\" INTEGER NOT NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"UpdatedAt\" TEXT NOT NULL\n);\n\nINSERT INTO \"__EFMigrationsHistory\" (\"MigrationId\", \"ProductVersion\")\nVALUES ('20240729105618_1.1.0-AddPkiTables', '9.0.4');\n\nCREATE TABLE \"Settings\" (\n \"Key\" TEXT NOT NULL CONSTRAINT \"PK_Settings\" PRIMARY KEY,\n \"Value\" TEXT NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"UpdatedAt\" TEXT NOT NULL\n);\n\nINSERT INTO \"__EFMigrationsHistory\" (\"MigrationId\", \"ProductVersion\")\nVALUES ('20240805073413_1.2.0-AddSettingsTable', '9.0.4');\n\nCREATE TABLE \"ef_temp_Aliases\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_Aliases\" PRIMARY KEY,\n \"BirthDate\" TEXT NOT NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"Email\" TEXT NULL,\n \"FirstName\" VARCHAR NULL,\n \"Gender\" VARCHAR NULL,\n \"LastName\" VARCHAR NULL,\n \"NickName\" VARCHAR NULL,\n \"UpdatedAt\" TEXT NOT NULL\n);\n\nINSERT INTO \"ef_temp_Aliases\" (\"Id\", \"BirthDate\", \"CreatedAt\", \"Email\", \"FirstName\", \"Gender\", \"LastName\", \"NickName\", \"UpdatedAt\")\nSELECT \"Id\", \"BirthDate\", \"CreatedAt\", \"Email\", \"FirstName\", \"Gender\", \"LastName\", \"NickName\", \"UpdatedAt\"\nFROM \"Aliases\";\n\nCOMMIT;\n\nPRAGMA foreign_keys = 0;\n\nBEGIN TRANSACTION;\nDROP TABLE \"Aliases\";\n\nALTER TABLE \"ef_temp_Aliases\" RENAME TO \"Aliases\";\n\nCOMMIT;\n\nPRAGMA foreign_keys = 1;\n\nINSERT INTO \"__EFMigrationsHistory\" (\"MigrationId\", \"ProductVersion\")\nVALUES ('20240805122422_1.3.0-UpdateIdentityStructure', '9.0.4');\n\nBEGIN TRANSACTION;\nCREATE TABLE \"ef_temp_Credentials\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_Credentials\" PRIMARY KEY,\n \"AliasId\" TEXT NOT NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"Notes\" TEXT NULL,\n \"ServiceId\" TEXT NOT NULL,\n \"UpdatedAt\" TEXT NOT NULL,\n \"Username\" TEXT NULL,\n CONSTRAINT \"FK_Credentials_Aliases_AliasId\" FOREIGN KEY (\"AliasId\") REFERENCES \"Aliases\" (\"Id\") ON DELETE CASCADE,\n CONSTRAINT \"FK_Credentials_Services_ServiceId\" FOREIGN KEY (\"ServiceId\") REFERENCES \"Services\" (\"Id\") ON DELETE CASCADE\n);\n\nINSERT INTO \"ef_temp_Credentials\" (\"Id\", \"AliasId\", \"CreatedAt\", \"Notes\", \"ServiceId\", \"UpdatedAt\", \"Username\")\nSELECT \"Id\", \"AliasId\", \"CreatedAt\", \"Notes\", \"ServiceId\", \"UpdatedAt\", \"Username\"\nFROM \"Credentials\";\n\nCOMMIT;\n\nPRAGMA foreign_keys = 0;\n\nBEGIN TRANSACTION;\nDROP TABLE \"Credentials\";\n\nALTER TABLE \"ef_temp_Credentials\" RENAME TO \"Credentials\";\n\nCOMMIT;\n\nPRAGMA foreign_keys = 1;\n\nBEGIN TRANSACTION;\nCREATE INDEX \"IX_Credentials_AliasId\" ON \"Credentials\" (\"AliasId\");\n\nCREATE INDEX \"IX_Credentials_ServiceId\" ON \"Credentials\" (\"ServiceId\");\n\nCOMMIT;\n\nINSERT INTO \"__EFMigrationsHistory\" (\"MigrationId\", \"ProductVersion\")\nVALUES ('20240812141727_1.3.1-MakeUsernameOptional', '9.0.4');\n\nBEGIN TRANSACTION;\nALTER TABLE \"Settings\" ADD \"IsDeleted\" INTEGER NOT NULL DEFAULT 0;\n\nALTER TABLE \"Services\" ADD \"IsDeleted\" INTEGER NOT NULL DEFAULT 0;\n\nALTER TABLE \"Passwords\" ADD \"IsDeleted\" INTEGER NOT NULL DEFAULT 0;\n\nALTER TABLE \"EncryptionKeys\" ADD \"IsDeleted\" INTEGER NOT NULL DEFAULT 0;\n\nALTER TABLE \"Credentials\" ADD \"IsDeleted\" INTEGER NOT NULL DEFAULT 0;\n\nALTER TABLE \"Attachment\" ADD \"IsDeleted\" INTEGER NOT NULL DEFAULT 0;\n\nALTER TABLE \"Aliases\" ADD \"IsDeleted\" INTEGER NOT NULL DEFAULT 0;\n\nINSERT INTO \"__EFMigrationsHistory\" (\"MigrationId\", \"ProductVersion\")\nVALUES ('20240916105320_1.4.0-AddSyncSupport', '9.0.4');\n\nALTER TABLE \"Attachment\" RENAME TO \"Attachments\";\n\nCREATE TABLE \"ef_temp_Attachments\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_Attachments\" PRIMARY KEY,\n \"Blob\" BLOB NOT NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"CredentialId\" TEXT NOT NULL,\n \"Filename\" TEXT NOT NULL,\n \"IsDeleted\" INTEGER NOT NULL,\n \"UpdatedAt\" TEXT NOT NULL,\n CONSTRAINT \"FK_Attachments_Credentials_CredentialId\" FOREIGN KEY (\"CredentialId\") REFERENCES \"Credentials\" (\"Id\") ON DELETE CASCADE\n);\n\nINSERT INTO \"ef_temp_Attachments\" (\"Id\", \"Blob\", \"CreatedAt\", \"CredentialId\", \"Filename\", \"IsDeleted\", \"UpdatedAt\")\nSELECT \"Id\", \"Blob\", \"CreatedAt\", \"CredentialId\", \"Filename\", \"IsDeleted\", \"UpdatedAt\"\nFROM \"Attachments\";\n\nCOMMIT;\n\nPRAGMA foreign_keys = 0;\n\nBEGIN TRANSACTION;\nDROP TABLE \"Attachments\";\n\nALTER TABLE \"ef_temp_Attachments\" RENAME TO \"Attachments\";\n\nCOMMIT;\n\nPRAGMA foreign_keys = 1;\n\nBEGIN TRANSACTION;\nCREATE INDEX \"IX_Attachments_CredentialId\" ON \"Attachments\" (\"CredentialId\");\n\nCOMMIT;\n\nINSERT INTO \"__EFMigrationsHistory\" (\"MigrationId\", \"ProductVersion\")\nVALUES ('20240917191243_1.4.1-RenameAttachmentsPlural', '9.0.4');\n\nBEGIN TRANSACTION;\nCREATE TABLE \"TotpCodes\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_TotpCodes\" PRIMARY KEY,\n \"Name\" TEXT NOT NULL,\n \"SecretKey\" TEXT NOT NULL,\n \"CredentialId\" TEXT NOT NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"UpdatedAt\" TEXT NOT NULL,\n \"IsDeleted\" INTEGER NOT NULL,\n CONSTRAINT \"FK_TotpCodes_Credentials_CredentialId\" FOREIGN KEY (\"CredentialId\") REFERENCES \"Credentials\" (\"Id\") ON DELETE CASCADE\n);\n\nCREATE INDEX \"IX_TotpCodes_CredentialId\" ON \"TotpCodes\" (\"CredentialId\");\n\nINSERT INTO \"__EFMigrationsHistory\" (\"MigrationId\", \"ProductVersion\")\nVALUES ('20250310131554_1.5.0-AddTotpCodes', '9.0.4');\n\n\nPRAGMA foreign_keys = OFF;\n\n-- Clean up any existing temp tables first\nDROP TABLE IF EXISTS \"__EFMigrationsHistory_temp\";\nDROP TABLE IF EXISTS \"Aliases_temp\";\nDROP TABLE IF EXISTS \"Services_temp\";\nDROP TABLE IF EXISTS \"EncryptionKeys_temp\";\nDROP TABLE IF EXISTS \"Settings_temp\";\nDROP TABLE IF EXISTS \"Credentials_temp\";\nDROP TABLE IF EXISTS \"Attachments_temp\";\nDROP TABLE IF EXISTS \"Passwords_temp\";\nDROP TABLE IF EXISTS \"TotpCodes_temp\";\n\n-- Create backup tables for all data\nCREATE TABLE \"__EFMigrationsHistory_temp\" AS SELECT * FROM \"__EFMigrationsHistory\";\nCREATE TABLE \"Aliases_temp\" AS SELECT * FROM \"Aliases\";\nCREATE TABLE \"Services_temp\" AS SELECT * FROM \"Services\";\nCREATE TABLE \"EncryptionKeys_temp\" AS SELECT * FROM \"EncryptionKeys\";\nCREATE TABLE \"Settings_temp\" AS SELECT * FROM \"Settings\";\nCREATE TABLE \"Credentials_temp\" AS SELECT * FROM \"Credentials\";\nCREATE TABLE \"Attachments_temp\" AS SELECT * FROM \"Attachments\";\nCREATE TABLE \"Passwords_temp\" AS SELECT * FROM \"Passwords\";\nCREATE TABLE \"TotpCodes_temp\" AS SELECT * FROM \"TotpCodes\";\n\n-- Delete orphaned records that do not have a valid FK to the credential object\nDELETE FROM \"Attachments_temp\" WHERE \"CredentialId\" NOT IN (SELECT \"Id\" FROM \"Credentials_temp\");\nDELETE FROM \"Passwords_temp\" WHERE \"CredentialId\" NOT IN (SELECT \"Id\" FROM \"Credentials_temp\");\nDELETE FROM \"TotpCodes_temp\" WHERE \"CredentialId\" NOT IN (SELECT \"Id\" FROM \"Credentials_temp\");\n\n-- Delete orphaned credentials that do not have valid FKs to alias or service objects\nDELETE FROM \"Credentials_temp\" WHERE \"AliasId\" NOT IN (SELECT \"Id\" FROM \"Aliases_temp\");\nDELETE FROM \"Credentials_temp\" WHERE \"ServiceId\" NOT IN (SELECT \"Id\" FROM \"Services_temp\");\n\n-- After cleaning credentials, clean dependent tables again in case we removed credentials\nDELETE FROM \"Attachments_temp\" WHERE \"CredentialId\" NOT IN (SELECT \"Id\" FROM \"Credentials_temp\");\nDELETE FROM \"Passwords_temp\" WHERE \"CredentialId\" NOT IN (SELECT \"Id\" FROM \"Credentials_temp\");\nDELETE FROM \"TotpCodes_temp\" WHERE \"CredentialId\" NOT IN (SELECT \"Id\" FROM \"Credentials_temp\");\n\n-- Drop all existing tables\nDROP TABLE \"TotpCodes\";\nDROP TABLE \"Passwords\";\nDROP TABLE \"Attachments\";\nDROP TABLE \"Credentials\";\nDROP TABLE \"Settings\";\nDROP TABLE \"EncryptionKeys\";\nDROP TABLE \"Services\";\nDROP TABLE \"Aliases\";\nDROP TABLE \"__EFMigrationsHistory\";\n\n-- Recreate tables with proper constraints (no dependencies first)\nCREATE TABLE \"__EFMigrationsHistory\" (\n \"MigrationId\" TEXT NOT NULL CONSTRAINT \"PK___EFMigrationsHistory\" PRIMARY KEY,\n \"ProductVersion\" TEXT NOT NULL\n);\n\nCREATE TABLE \"Aliases\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_Aliases\" PRIMARY KEY,\n \"BirthDate\" TEXT NOT NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"Email\" TEXT NULL,\n \"FirstName\" VARCHAR NULL,\n \"Gender\" VARCHAR NULL,\n \"LastName\" VARCHAR NULL,\n \"NickName\" VARCHAR NULL,\n \"UpdatedAt\" TEXT NOT NULL,\n \"IsDeleted\" INTEGER NOT NULL DEFAULT 0\n);\n\nCREATE TABLE \"Services\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_Services\" PRIMARY KEY,\n \"Name\" TEXT NULL,\n \"Url\" TEXT NULL,\n \"Logo\" BLOB NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"UpdatedAt\" TEXT NOT NULL,\n \"IsDeleted\" INTEGER NOT NULL DEFAULT 0\n);\n\nCREATE TABLE \"EncryptionKeys\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_EncryptionKeys\" PRIMARY KEY,\n \"PublicKey\" TEXT NOT NULL,\n \"PrivateKey\" TEXT NOT NULL,\n \"IsPrimary\" INTEGER NOT NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"UpdatedAt\" TEXT NOT NULL,\n \"IsDeleted\" INTEGER NOT NULL DEFAULT 0\n);\n\nCREATE TABLE \"Settings\" (\n \"Key\" TEXT NOT NULL CONSTRAINT \"PK_Settings\" PRIMARY KEY,\n \"Value\" TEXT NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"UpdatedAt\" TEXT NOT NULL,\n \"IsDeleted\" INTEGER NOT NULL DEFAULT 0\n);\n\n-- Tables with foreign keys\nCREATE TABLE \"Credentials\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_Credentials\" PRIMARY KEY,\n \"AliasId\" TEXT NOT NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"Notes\" TEXT NULL,\n \"ServiceId\" TEXT NOT NULL,\n \"UpdatedAt\" TEXT NOT NULL,\n \"Username\" TEXT NULL,\n \"IsDeleted\" INTEGER NOT NULL DEFAULT 0,\n CONSTRAINT \"FK_Credentials_Aliases_AliasId\" FOREIGN KEY (\"AliasId\") REFERENCES \"Aliases\" (\"Id\") ON DELETE CASCADE,\n CONSTRAINT \"FK_Credentials_Services_ServiceId\" FOREIGN KEY (\"ServiceId\") REFERENCES \"Services\" (\"Id\") ON DELETE CASCADE\n);\n\nCREATE TABLE \"Attachments\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_Attachments\" PRIMARY KEY,\n \"Blob\" BLOB NOT NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"CredentialId\" TEXT NOT NULL,\n \"Filename\" TEXT NOT NULL,\n \"IsDeleted\" INTEGER NOT NULL DEFAULT 0,\n \"UpdatedAt\" TEXT NOT NULL,\n CONSTRAINT \"FK_Attachments_Credentials_CredentialId\" FOREIGN KEY (\"CredentialId\") REFERENCES \"Credentials\" (\"Id\") ON DELETE CASCADE\n);\n\nCREATE TABLE \"Passwords\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_Passwords\" PRIMARY KEY,\n \"Value\" TEXT NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"UpdatedAt\" TEXT NOT NULL,\n \"CredentialId\" TEXT NOT NULL,\n \"IsDeleted\" INTEGER NOT NULL DEFAULT 0,\n CONSTRAINT \"FK_Passwords_Credentials_CredentialId\" FOREIGN KEY (\"CredentialId\") REFERENCES \"Credentials\" (\"Id\") ON DELETE CASCADE\n);\n\nCREATE TABLE \"TotpCodes\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_TotpCodes\" PRIMARY KEY,\n \"Name\" TEXT NOT NULL,\n \"SecretKey\" TEXT NOT NULL,\n \"CredentialId\" TEXT NOT NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"UpdatedAt\" TEXT NOT NULL,\n \"IsDeleted\" INTEGER NOT NULL DEFAULT 0,\n CONSTRAINT \"FK_TotpCodes_Credentials_CredentialId\" FOREIGN KEY (\"CredentialId\") REFERENCES \"Credentials\" (\"Id\") ON DELETE CASCADE\n);\n\n\n-- Restore data from temp tables\nINSERT INTO \"__EFMigrationsHistory\" SELECT * FROM \"__EFMigrationsHistory_temp\";\nINSERT INTO \"Aliases\" SELECT * FROM \"Aliases_temp\";\nINSERT INTO \"Services\" SELECT * FROM \"Services_temp\";\nINSERT INTO \"EncryptionKeys\" SELECT * FROM \"EncryptionKeys_temp\";\nINSERT INTO \"Settings\" SELECT * FROM \"Settings_temp\";\nINSERT INTO \"Credentials\" SELECT * FROM \"Credentials_temp\";\nINSERT INTO \"Attachments\" SELECT * FROM \"Attachments_temp\";\nINSERT INTO \"Passwords\" SELECT * FROM \"Passwords_temp\";\nINSERT INTO \"TotpCodes\" SELECT * FROM \"TotpCodes_temp\";\n\n-- =====================================================================================\n-- Date Format Normalization Migration\n-- =====================================================================================\n-- This migration normalizes ALL date fields to the standard format: 'yyyy-MM-dd HH:mm:ss.fff'\n-- Previously the different clients used different date formats which complicate date parsing.\n-- From version 0.24.0 onwards, all new dates are stored in this standard format.\n\n-- Update Aliases table (CreatedAt, UpdatedAt, BirthDate)\nUPDATE \"Aliases\" SET \"CreatedAt\" =\n CASE\n -- Already in correct format (yyyy-MM-dd HH:mm:ss.fff) - no change\n WHEN \"CreatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9] [0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9][0-9][0-9]'\n THEN \"CreatedAt\"\n\n -- ISO 8601 with milliseconds (yyyy-MM-ddTHH:mm:ss.fffZ) -> Replace T with space, remove Z and everything after .fff\n WHEN \"CreatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]T[0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9]*'\n THEN substr(\"CreatedAt\", 1, 10) || ' ' || substr(\"CreatedAt\", 12, 12)\n\n -- Without milliseconds (yyyy-MM-dd HH:mm:ss or yyyy-MM-ddTHH:mm:ssZ) -> Add .000\n WHEN \"CreatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9][T ][0-9][0-9]:[0-9][0-9]:[0-9][0-9]*'\n THEN substr(\"CreatedAt\", 1, 10) || ' ' || substr(replace(\"CreatedAt\", 'T', ' '), 12, 8) || '.000'\n\n -- Fallback: if none match, keep as-is (edge case)\n ELSE \"CreatedAt\"\n END;\n\nUPDATE \"Aliases\" SET \"UpdatedAt\" =\n CASE\n WHEN \"UpdatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9] [0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9][0-9][0-9]'\n THEN \"UpdatedAt\"\n WHEN \"UpdatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]T[0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9]*'\n THEN substr(\"UpdatedAt\", 1, 10) || ' ' || substr(\"UpdatedAt\", 12, 12)\n WHEN \"UpdatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9][T ][0-9][0-9]:[0-9][0-9]:[0-9][0-9]*'\n THEN substr(\"UpdatedAt\", 1, 10) || ' ' || substr(replace(\"UpdatedAt\", 'T', ' '), 12, 8) || '.000'\n ELSE \"UpdatedAt\"\n END;\n\n-- BirthDate: Always set time to 00:00:00 (no milliseconds for birth dates)\nUPDATE \"Aliases\" SET \"BirthDate\" =\n CASE\n -- If empty or already '0001-01-01 00:00:00', keep as-is\n WHEN \"BirthDate\" = '' OR \"BirthDate\" = '0001-01-01 00:00:00'\n THEN \"BirthDate\"\n\n -- If already in correct format (yyyy-MM-dd 00:00:00), keep as-is\n WHEN \"BirthDate\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9] 00:00:00'\n THEN \"BirthDate\"\n\n -- Extract date part and set time to 00:00:00\n WHEN \"BirthDate\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]*'\n THEN substr(\"BirthDate\", 1, 10) || ' 00:00:00'\n\n -- Fallback\n ELSE \"BirthDate\"\n END;\n\n-- Update Services table (CreatedAt, UpdatedAt)\nUPDATE \"Services\" SET \"CreatedAt\" =\n CASE\n WHEN \"CreatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9] [0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9][0-9][0-9]'\n THEN \"CreatedAt\"\n WHEN \"CreatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]T[0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9]*'\n THEN substr(\"CreatedAt\", 1, 10) || ' ' || substr(\"CreatedAt\", 12, 12)\n WHEN \"CreatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9][T ][0-9][0-9]:[0-9][0-9]:[0-9][0-9]*'\n THEN substr(\"CreatedAt\", 1, 10) || ' ' || substr(replace(\"CreatedAt\", 'T', ' '), 12, 8) || '.000'\n ELSE \"CreatedAt\"\n END;\n\nUPDATE \"Services\" SET \"UpdatedAt\" =\n CASE\n WHEN \"UpdatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9] [0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9][0-9][0-9]'\n THEN \"UpdatedAt\"\n WHEN \"UpdatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]T[0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9]*'\n THEN substr(\"UpdatedAt\", 1, 10) || ' ' || substr(\"UpdatedAt\", 12, 12)\n WHEN \"UpdatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9][T ][0-9][0-9]:[0-9][0-9]:[0-9][0-9]*'\n THEN substr(\"UpdatedAt\", 1, 10) || ' ' || substr(replace(\"UpdatedAt\", 'T', ' '), 12, 8) || '.000'\n ELSE \"UpdatedAt\"\n END;\n\n-- Update EncryptionKeys table (CreatedAt, UpdatedAt)\nUPDATE \"EncryptionKeys\" SET \"CreatedAt\" =\n CASE\n WHEN \"CreatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9] [0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9][0-9][0-9]'\n THEN \"CreatedAt\"\n WHEN \"CreatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]T[0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9]*'\n THEN substr(\"CreatedAt\", 1, 10) || ' ' || substr(\"CreatedAt\", 12, 12)\n WHEN \"CreatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9][T ][0-9][0-9]:[0-9][0-9]:[0-9][0-9]*'\n THEN substr(\"CreatedAt\", 1, 10) || ' ' || substr(replace(\"CreatedAt\", 'T', ' '), 12, 8) || '.000'\n ELSE \"CreatedAt\"\n END;\n\nUPDATE \"EncryptionKeys\" SET \"UpdatedAt\" =\n CASE\n WHEN \"UpdatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9] [0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9][0-9][0-9]'\n THEN \"UpdatedAt\"\n WHEN \"UpdatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]T[0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9]*'\n THEN substr(\"UpdatedAt\", 1, 10) || ' ' || substr(\"UpdatedAt\", 12, 12)\n WHEN \"UpdatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9][T ][0-9][0-9]:[0-9][0-9]:[0-9][0-9]*'\n THEN substr(\"UpdatedAt\", 1, 10) || ' ' || substr(replace(\"UpdatedAt\", 'T', ' '), 12, 8) || '.000'\n ELSE \"UpdatedAt\"\n END;\n\n-- Update Settings table (CreatedAt, UpdatedAt)\nUPDATE \"Settings\" SET \"CreatedAt\" =\n CASE\n WHEN \"CreatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9] [0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9][0-9][0-9]'\n THEN \"CreatedAt\"\n WHEN \"CreatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]T[0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9]*'\n THEN substr(\"CreatedAt\", 1, 10) || ' ' || substr(\"CreatedAt\", 12, 12)\n WHEN \"CreatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9][T ][0-9][0-9]:[0-9][0-9]:[0-9][0-9]*'\n THEN substr(\"CreatedAt\", 1, 10) || ' ' || substr(replace(\"CreatedAt\", 'T', ' '), 12, 8) || '.000'\n ELSE \"CreatedAt\"\n END;\n\nUPDATE \"Settings\" SET \"UpdatedAt\" =\n CASE\n WHEN \"UpdatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9] [0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9][0-9][0-9]'\n THEN \"UpdatedAt\"\n WHEN \"UpdatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]T[0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9]*'\n THEN substr(\"UpdatedAt\", 1, 10) || ' ' || substr(\"UpdatedAt\", 12, 12)\n WHEN \"UpdatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9][T ][0-9][0-9]:[0-9][0-9]:[0-9][0-9]*'\n THEN substr(\"UpdatedAt\", 1, 10) || ' ' || substr(replace(\"UpdatedAt\", 'T', ' '), 12, 8) || '.000'\n ELSE \"UpdatedAt\"\n END;\n\n-- Update Credentials table (CreatedAt, UpdatedAt)\nUPDATE \"Credentials\" SET \"CreatedAt\" =\n CASE\n WHEN \"CreatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9] [0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9][0-9][0-9]'\n THEN \"CreatedAt\"\n WHEN \"CreatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]T[0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9]*'\n THEN substr(\"CreatedAt\", 1, 10) || ' ' || substr(\"CreatedAt\", 12, 12)\n WHEN \"CreatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9][T ][0-9][0-9]:[0-9][0-9]:[0-9][0-9]*'\n THEN substr(\"CreatedAt\", 1, 10) || ' ' || substr(replace(\"CreatedAt\", 'T', ' '), 12, 8) || '.000'\n ELSE \"CreatedAt\"\n END;\n\nUPDATE \"Credentials\" SET \"UpdatedAt\" =\n CASE\n WHEN \"UpdatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9] [0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9][0-9][0-9]'\n THEN \"UpdatedAt\"\n WHEN \"UpdatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]T[0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9]*'\n THEN substr(\"UpdatedAt\", 1, 10) || ' ' || substr(\"UpdatedAt\", 12, 12)\n WHEN \"UpdatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9][T ][0-9][0-9]:[0-9][0-9]:[0-9][0-9]*'\n THEN substr(\"UpdatedAt\", 1, 10) || ' ' || substr(replace(\"UpdatedAt\", 'T', ' '), 12, 8) || '.000'\n ELSE \"UpdatedAt\"\n END;\n\n-- Update Attachments table (CreatedAt, UpdatedAt)\nUPDATE \"Attachments\" SET \"CreatedAt\" =\n CASE\n WHEN \"CreatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9] [0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9][0-9][0-9]'\n THEN \"CreatedAt\"\n WHEN \"CreatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]T[0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9]*'\n THEN substr(\"CreatedAt\", 1, 10) || ' ' || substr(\"CreatedAt\", 12, 12)\n WHEN \"CreatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9][T ][0-9][0-9]:[0-9][0-9]:[0-9][0-9]*'\n THEN substr(\"CreatedAt\", 1, 10) || ' ' || substr(replace(\"CreatedAt\", 'T', ' '), 12, 8) || '.000'\n ELSE \"CreatedAt\"\n END;\n\nUPDATE \"Attachments\" SET \"UpdatedAt\" =\n CASE\n WHEN \"UpdatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9] [0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9][0-9][0-9]'\n THEN \"UpdatedAt\"\n WHEN \"UpdatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]T[0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9]*'\n THEN substr(\"UpdatedAt\", 1, 10) || ' ' || substr(\"UpdatedAt\", 12, 12)\n WHEN \"UpdatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9][T ][0-9][0-9]:[0-9][0-9]:[0-9][0-9]*'\n THEN substr(\"UpdatedAt\", 1, 10) || ' ' || substr(replace(\"UpdatedAt\", 'T', ' '), 12, 8) || '.000'\n ELSE \"UpdatedAt\"\n END;\n\n-- Update Passwords table (CreatedAt, UpdatedAt)\nUPDATE \"Passwords\" SET \"CreatedAt\" =\n CASE\n WHEN \"CreatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9] [0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9][0-9][0-9]'\n THEN \"CreatedAt\"\n WHEN \"CreatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]T[0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9]*'\n THEN substr(\"CreatedAt\", 1, 10) || ' ' || substr(\"CreatedAt\", 12, 12)\n WHEN \"CreatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9][T ][0-9][0-9]:[0-9][0-9]:[0-9][0-9]*'\n THEN substr(\"CreatedAt\", 1, 10) || ' ' || substr(replace(\"CreatedAt\", 'T', ' '), 12, 8) || '.000'\n ELSE \"CreatedAt\"\n END;\n\nUPDATE \"Passwords\" SET \"UpdatedAt\" =\n CASE\n WHEN \"UpdatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9] [0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9][0-9][0-9]'\n THEN \"UpdatedAt\"\n WHEN \"UpdatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]T[0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9]*'\n THEN substr(\"UpdatedAt\", 1, 10) || ' ' || substr(\"UpdatedAt\", 12, 12)\n WHEN \"UpdatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9][T ][0-9][0-9]:[0-9][0-9]:[0-9][0-9]*'\n THEN substr(\"UpdatedAt\", 1, 10) || ' ' || substr(replace(\"UpdatedAt\", 'T', ' '), 12, 8) || '.000'\n ELSE \"UpdatedAt\"\n END;\n\n-- Update TotpCodes table (CreatedAt, UpdatedAt)\nUPDATE \"TotpCodes\" SET \"CreatedAt\" =\n CASE\n WHEN \"CreatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9] [0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9][0-9][0-9]'\n THEN \"CreatedAt\"\n WHEN \"CreatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]T[0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9]*'\n THEN substr(\"CreatedAt\", 1, 10) || ' ' || substr(\"CreatedAt\", 12, 12)\n WHEN \"CreatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9][T ][0-9][0-9]:[0-9][0-9]:[0-9][0-9]*'\n THEN substr(\"CreatedAt\", 1, 10) || ' ' || substr(replace(\"CreatedAt\", 'T', ' '), 12, 8) || '.000'\n ELSE \"CreatedAt\"\n END;\n\nUPDATE \"TotpCodes\" SET \"UpdatedAt\" =\n CASE\n WHEN \"UpdatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9] [0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9][0-9][0-9]'\n THEN \"UpdatedAt\"\n WHEN \"UpdatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]T[0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9]*'\n THEN substr(\"UpdatedAt\", 1, 10) || ' ' || substr(\"UpdatedAt\", 12, 12)\n WHEN \"UpdatedAt\" GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9][T ][0-9][0-9]:[0-9][0-9]:[0-9][0-9]*'\n THEN substr(\"UpdatedAt\", 1, 10) || ' ' || substr(replace(\"UpdatedAt\", 'T', ' '), 12, 8) || '.000'\n ELSE \"UpdatedAt\"\n END;\n\n-- =====================================================================================\n-- End of Date Format Normalization Migration\n-- =====================================================================================\n\n-- Recreate indexes\nCREATE INDEX \"IX_Credentials_AliasId\" ON \"Credentials\" (\"AliasId\");\nCREATE INDEX \"IX_Credentials_ServiceId\" ON \"Credentials\" (\"ServiceId\");\nCREATE INDEX \"IX_Attachments_CredentialId\" ON \"Attachments\" (\"CredentialId\");\nCREATE INDEX \"IX_Passwords_CredentialId\" ON \"Passwords\" (\"CredentialId\");\nCREATE INDEX \"IX_TotpCodes_CredentialId\" ON \"TotpCodes\" (\"CredentialId\");\n\n-- Clean up temp tables\nDROP TABLE \"__EFMigrationsHistory_temp\";\nDROP TABLE \"Aliases_temp\";\nDROP TABLE \"Services_temp\";\nDROP TABLE \"EncryptionKeys_temp\";\nDROP TABLE \"Settings_temp\";\nDROP TABLE \"Credentials_temp\";\nDROP TABLE \"Attachments_temp\";\nDROP TABLE \"Passwords_temp\";\nDROP TABLE \"TotpCodes_temp\";\n\nPRAGMA foreign_keys = ON;\n\n\nCREATE TABLE \"Passkeys\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_Passkeys\" PRIMARY KEY,\n \"RpId\" TEXT COLLATE NOCASE NOT NULL,\n \"UserHandle\" BLOB NOT NULL,\n \"PublicKey\" TEXT NOT NULL,\n \"PrivateKey\" TEXT NOT NULL,\n \"PrfKey\" BLOB NULL,\n \"DisplayName\" TEXT NOT NULL,\n \"AdditionalData\" BLOB NULL,\n \"CredentialId\" TEXT NOT NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"UpdatedAt\" TEXT NOT NULL,\n \"IsDeleted\" INTEGER NOT NULL,\n CONSTRAINT \"FK_Passkeys_Credentials_CredentialId\" FOREIGN KEY (\"CredentialId\") REFERENCES \"Credentials\" (\"Id\") ON DELETE CASCADE\n);\n\nCREATE INDEX \"IX_Passkeys_CredentialId\" ON \"Passkeys\" (\"CredentialId\");\n\nCREATE INDEX \"IX_Passkeys_RpId\" ON \"Passkeys\" (\"RpId\");\n\nINSERT INTO \"__EFMigrationsHistory\" (\"MigrationId\", \"ProductVersion\")\nVALUES ('20251014122838_1.6.0-AddPasskeys', '9.0.4');\n\nALTER TABLE \"TotpCodes\" RENAME COLUMN \"CredentialId\" TO \"ItemId\";\n\nDROP INDEX IF EXISTS \"IX_TotpCodes_CredentialId\";\n\nCREATE INDEX IF NOT EXISTS \"IX_TotpCodes_ItemId\" ON \"TotpCodes\" (\"ItemId\");\n\nALTER TABLE \"Passkeys\" RENAME COLUMN \"CredentialId\" TO \"ItemId\";\n\nDROP INDEX IF EXISTS \"IX_Passkeys_CredentialId\";\n\nCREATE INDEX IF NOT EXISTS \"IX_Passkeys_ItemId\" ON \"Passkeys\" (\"ItemId\");\n\nALTER TABLE \"Attachments\" RENAME COLUMN \"CredentialId\" TO \"ItemId\";\n\nDROP INDEX IF EXISTS \"IX_Attachments_CredentialId\";\n\nCREATE INDEX IF NOT EXISTS \"IX_Attachments_ItemId\" ON \"Attachments\" (\"ItemId\");\n\nCREATE TABLE \"FieldDefinitions\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_FieldDefinitions\" PRIMARY KEY,\n \"FieldType\" TEXT NOT NULL,\n \"Label\" TEXT NOT NULL,\n \"IsMultiValue\" INTEGER NOT NULL,\n \"IsHidden\" INTEGER NOT NULL,\n \"EnableHistory\" INTEGER NOT NULL,\n \"Weight\" INTEGER NOT NULL,\n \"ApplicableToTypes\" TEXT NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"UpdatedAt\" TEXT NOT NULL,\n \"IsDeleted\" INTEGER NOT NULL\n);\n\nCREATE TABLE \"Folders\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_Folders\" PRIMARY KEY,\n \"Name\" TEXT NOT NULL,\n \"ParentFolderId\" TEXT NULL,\n \"Weight\" INTEGER NOT NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"UpdatedAt\" TEXT NOT NULL,\n \"IsDeleted\" INTEGER NOT NULL,\n CONSTRAINT \"FK_Folders_Folders_ParentFolderId\" FOREIGN KEY (\"ParentFolderId\") REFERENCES \"Folders\" (\"Id\") ON DELETE CASCADE\n);\n\nCREATE TABLE \"Logos\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_Logos\" PRIMARY KEY,\n \"Source\" TEXT NOT NULL,\n \"FileData\" BLOB NULL,\n \"MimeType\" TEXT NULL,\n \"FetchedAt\" TEXT NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"UpdatedAt\" TEXT NOT NULL,\n \"IsDeleted\" INTEGER NOT NULL\n);\n\nCREATE TABLE \"Tags\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_Tags\" PRIMARY KEY,\n \"Name\" TEXT NOT NULL,\n \"Color\" TEXT NULL,\n \"DisplayOrder\" INTEGER NOT NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"UpdatedAt\" TEXT NOT NULL,\n \"IsDeleted\" INTEGER NOT NULL\n);\n\nCREATE TABLE \"Items\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_Items\" PRIMARY KEY,\n \"Name\" TEXT NULL,\n \"ItemType\" TEXT NOT NULL,\n \"LogoId\" TEXT NULL,\n \"DeletedAt\" TEXT NULL,\n \"FolderId\" TEXT NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"UpdatedAt\" TEXT NOT NULL,\n \"IsDeleted\" INTEGER NOT NULL,\n CONSTRAINT \"FK_Items_Folders_FolderId\" FOREIGN KEY (\"FolderId\") REFERENCES \"Folders\" (\"Id\") ON DELETE SET NULL,\n CONSTRAINT \"FK_Items_Logos_LogoId\" FOREIGN KEY (\"LogoId\") REFERENCES \"Logos\" (\"Id\") ON DELETE SET NULL\n);\n\nCREATE TABLE \"FieldHistories\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_FieldHistories\" PRIMARY KEY,\n \"ItemId\" TEXT NOT NULL,\n \"FieldDefinitionId\" TEXT NULL,\n \"FieldKey\" TEXT NULL,\n \"ValueSnapshot\" TEXT NOT NULL,\n \"ChangedAt\" TEXT NOT NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"UpdatedAt\" TEXT NOT NULL,\n \"IsDeleted\" INTEGER NOT NULL,\n CONSTRAINT \"FK_FieldHistories_FieldDefinitions_FieldDefinitionId\" FOREIGN KEY (\"FieldDefinitionId\") REFERENCES \"FieldDefinitions\" (\"Id\") ON DELETE CASCADE,\n CONSTRAINT \"FK_FieldHistories_Items_ItemId\" FOREIGN KEY (\"ItemId\") REFERENCES \"Items\" (\"Id\") ON DELETE CASCADE\n);\n\nCREATE TABLE \"FieldValues\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_FieldValues\" PRIMARY KEY,\n \"ItemId\" TEXT NOT NULL,\n \"FieldDefinitionId\" TEXT NULL,\n \"FieldKey\" TEXT NULL,\n \"Value\" TEXT NULL,\n \"Weight\" INTEGER NOT NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"UpdatedAt\" TEXT NOT NULL,\n \"IsDeleted\" INTEGER NOT NULL,\n CONSTRAINT \"FK_FieldValues_FieldDefinitions_FieldDefinitionId\" FOREIGN KEY (\"FieldDefinitionId\") REFERENCES \"FieldDefinitions\" (\"Id\") ON DELETE CASCADE,\n CONSTRAINT \"FK_FieldValues_Items_ItemId\" FOREIGN KEY (\"ItemId\") REFERENCES \"Items\" (\"Id\") ON DELETE CASCADE\n);\n\nCREATE TABLE \"ItemTags\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_ItemTags\" PRIMARY KEY,\n \"ItemId\" TEXT NOT NULL,\n \"TagId\" TEXT NOT NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"UpdatedAt\" TEXT NOT NULL,\n \"IsDeleted\" INTEGER NOT NULL,\n CONSTRAINT \"FK_ItemTags_Items_ItemId\" FOREIGN KEY (\"ItemId\") REFERENCES \"Items\" (\"Id\") ON DELETE CASCADE,\n CONSTRAINT \"FK_ItemTags_Tags_TagId\" FOREIGN KEY (\"TagId\") REFERENCES \"Tags\" (\"Id\") ON DELETE CASCADE\n);\n\nCREATE INDEX \"IX_FieldHistories_FieldDefinitionId\" ON \"FieldHistories\" (\"FieldDefinitionId\");\n\nCREATE INDEX \"IX_FieldHistories_ItemId\" ON \"FieldHistories\" (\"ItemId\");\n\nCREATE INDEX \"IX_FieldValues_FieldDefinitionId\" ON \"FieldValues\" (\"FieldDefinitionId\");\n\nCREATE INDEX \"IX_FieldValues_FieldKey\" ON \"FieldValues\" (\"FieldKey\");\n\nCREATE INDEX \"IX_FieldValues_ItemId\" ON \"FieldValues\" (\"ItemId\");\n\nCREATE INDEX \"IX_FieldValues_ItemId_FieldDefinitionId_Weight\" ON \"FieldValues\" (\"ItemId\", \"FieldDefinitionId\", \"Weight\");\n\nCREATE INDEX \"IX_FieldValues_ItemId_FieldKey\" ON \"FieldValues\" (\"ItemId\", \"FieldKey\");\n\nCREATE INDEX \"IX_Folders_ParentFolderId\" ON \"Folders\" (\"ParentFolderId\");\n\nCREATE INDEX \"IX_Items_FolderId\" ON \"Items\" (\"FolderId\");\n\nCREATE INDEX \"IX_Items_LogoId\" ON \"Items\" (\"LogoId\");\n\nCREATE INDEX \"IX_ItemTags_ItemId\" ON \"ItemTags\" (\"ItemId\");\n\nCREATE UNIQUE INDEX \"IX_ItemTags_ItemId_TagId\" ON \"ItemTags\" (\"ItemId\", \"TagId\");\n\nCREATE INDEX \"IX_ItemTags_TagId\" ON \"ItemTags\" (\"TagId\");\n\nCREATE UNIQUE INDEX \"IX_Logos_Source\" ON \"Logos\" (\"Source\");\n\nCREATE INDEX \"IX_Tags_Name\" ON \"Tags\" (\"Name\");\n\n\n INSERT INTO Items (Id, Name, ItemType, LogoId, FolderId, CreatedAt, UpdatedAt, IsDeleted)\n SELECT\n c.Id,\n s.Name AS Name,\n CASE\n WHEN a.Id IS NOT NULL AND (\n (a.FirstName IS NOT NULL AND a.FirstName != '') OR\n (a.LastName IS NOT NULL AND a.LastName != '') OR\n (a.Gender IS NOT NULL AND a.Gender != '') OR\n (a.BirthDate IS NOT NULL AND a.BirthDate != '' AND a.BirthDate NOT LIKE '0001-%')\n ) THEN 'Alias'\n ELSE 'Login'\n END AS ItemType,\n NULL AS LogoId,\n NULL AS FolderId,\n c.CreatedAt,\n c.UpdatedAt,\n c.IsDeleted\n FROM Credentials c\n LEFT JOIN Services s ON s.Id = c.ServiceId\n LEFT JOIN Aliases a ON a.Id = c.AliasId;\n \n\n\n INSERT INTO Logos (Id, Source, FileData, MimeType, FetchedAt, CreatedAt, UpdatedAt, IsDeleted)\n SELECT\n UPPER(SUBSTR(hex(randomblob(4)), 1, 8) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(6)), 1, 12)) AS Id,\n -- Extract and normalize hostname: remove protocol, path, lowercase, and www. prefix\n REPLACE(\n LOWER(\n SUBSTR(\n CASE\n WHEN s.Url LIKE 'https://%' THEN SUBSTR(s.Url, 9)\n WHEN s.Url LIKE 'http://%' THEN SUBSTR(s.Url, 8)\n ELSE s.Url\n END,\n 1,\n CASE\n WHEN INSTR(\n CASE\n WHEN s.Url LIKE 'https://%' THEN SUBSTR(s.Url, 9)\n WHEN s.Url LIKE 'http://%' THEN SUBSTR(s.Url, 8)\n ELSE s.Url\n END, '/') > 0\n THEN INSTR(\n CASE\n WHEN s.Url LIKE 'https://%' THEN SUBSTR(s.Url, 9)\n WHEN s.Url LIKE 'http://%' THEN SUBSTR(s.Url, 8)\n ELSE s.Url\n END, '/') - 1\n ELSE LENGTH(\n CASE\n WHEN s.Url LIKE 'https://%' THEN SUBSTR(s.Url, 9)\n WHEN s.Url LIKE 'http://%' THEN SUBSTR(s.Url, 8)\n ELSE s.Url\n END)\n END\n )\n ),\n 'www.', ''\n ) AS Source,\n s.Logo AS FileData,\n 'image/png' AS MimeType,\n NULL AS FetchedAt,\n MIN(s.CreatedAt) AS CreatedAt,\n MAX(s.UpdatedAt) AS UpdatedAt,\n 0 AS IsDeleted\n FROM Services s\n WHERE s.Logo IS NOT NULL AND s.Url IS NOT NULL AND s.Url != ''\n GROUP BY REPLACE(\n LOWER(\n SUBSTR(\n CASE\n WHEN s.Url LIKE 'https://%' THEN SUBSTR(s.Url, 9)\n WHEN s.Url LIKE 'http://%' THEN SUBSTR(s.Url, 8)\n ELSE s.Url\n END,\n 1,\n CASE\n WHEN INSTR(\n CASE\n WHEN s.Url LIKE 'https://%' THEN SUBSTR(s.Url, 9)\n WHEN s.Url LIKE 'http://%' THEN SUBSTR(s.Url, 8)\n ELSE s.Url\n END, '/') > 0\n THEN INSTR(\n CASE\n WHEN s.Url LIKE 'https://%' THEN SUBSTR(s.Url, 9)\n WHEN s.Url LIKE 'http://%' THEN SUBSTR(s.Url, 8)\n ELSE s.Url\n END, '/') - 1\n ELSE LENGTH(\n CASE\n WHEN s.Url LIKE 'https://%' THEN SUBSTR(s.Url, 9)\n WHEN s.Url LIKE 'http://%' THEN SUBSTR(s.Url, 8)\n ELSE s.Url\n END)\n END\n )\n ),\n 'www.', ''\n );\n \n\n\n UPDATE Items\n SET LogoId = (\n SELECT l.Id FROM Logos l\n INNER JOIN Services s ON REPLACE(\n LOWER(\n SUBSTR(\n CASE\n WHEN s.Url LIKE 'https://%' THEN SUBSTR(s.Url, 9)\n WHEN s.Url LIKE 'http://%' THEN SUBSTR(s.Url, 8)\n ELSE s.Url\n END,\n 1,\n CASE\n WHEN INSTR(\n CASE\n WHEN s.Url LIKE 'https://%' THEN SUBSTR(s.Url, 9)\n WHEN s.Url LIKE 'http://%' THEN SUBSTR(s.Url, 8)\n ELSE s.Url\n END, '/') > 0\n THEN INSTR(\n CASE\n WHEN s.Url LIKE 'https://%' THEN SUBSTR(s.Url, 9)\n WHEN s.Url LIKE 'http://%' THEN SUBSTR(s.Url, 8)\n ELSE s.Url\n END, '/') - 1\n ELSE LENGTH(\n CASE\n WHEN s.Url LIKE 'https://%' THEN SUBSTR(s.Url, 9)\n WHEN s.Url LIKE 'http://%' THEN SUBSTR(s.Url, 8)\n ELSE s.Url\n END)\n END\n )\n ),\n 'www.', ''\n ) = l.Source\n INNER JOIN Credentials c ON c.ServiceId = s.Id\n WHERE c.Id = Items.Id\n LIMIT 1\n )\n WHERE EXISTS (\n SELECT 1 FROM Credentials c\n INNER JOIN Services s ON s.Id = c.ServiceId\n WHERE c.Id = Items.Id AND s.Logo IS NOT NULL\n );\n \n\n\n INSERT INTO FieldValues (Id, ItemId, FieldDefinitionId, FieldKey, Value, Weight, CreatedAt, UpdatedAt, IsDeleted)\n SELECT\n UPPER(SUBSTR(hex(randomblob(4)), 1, 8) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(6)), 1, 12)) AS Id,\n c.Id AS ItemId,\n NULL AS FieldDefinitionId,\n 'login.url' AS FieldKey,\n s.Url AS Value,\n 0 AS Weight,\n s.UpdatedAt AS CreatedAt,\n s.UpdatedAt AS UpdatedAt,\n 0 AS IsDeleted\n FROM Credentials c\n INNER JOIN Services s ON s.Id = c.ServiceId\n WHERE s.Url IS NOT NULL AND s.Url != '';\n \n\n\n INSERT INTO FieldValues (Id, ItemId, FieldDefinitionId, FieldKey, Value, Weight, CreatedAt, UpdatedAt, IsDeleted)\n SELECT\n UPPER(SUBSTR(hex(randomblob(4)), 1, 8) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(6)), 1, 12)) AS Id,\n c.Id AS ItemId,\n NULL AS FieldDefinitionId,\n 'login.username' AS FieldKey,\n c.Username AS Value,\n 0 AS Weight,\n c.UpdatedAt AS CreatedAt,\n c.UpdatedAt AS UpdatedAt,\n 0 AS IsDeleted\n FROM Credentials c\n WHERE c.Username IS NOT NULL AND c.Username != '';\n \n\n\n INSERT INTO FieldValues (Id, ItemId, FieldDefinitionId, FieldKey, Value, Weight, CreatedAt, UpdatedAt, IsDeleted)\n SELECT\n UPPER(SUBSTR(hex(randomblob(4)), 1, 8) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(6)), 1, 12)) AS Id,\n c.Id AS ItemId,\n NULL AS FieldDefinitionId,\n 'login.notes' AS FieldKey,\n c.Notes AS Value,\n 0 AS Weight,\n c.UpdatedAt AS CreatedAt,\n c.UpdatedAt AS UpdatedAt,\n 0 AS IsDeleted\n FROM Credentials c\n WHERE c.Notes IS NOT NULL AND c.Notes != '';\n \n\n\n INSERT INTO FieldValues (Id, ItemId, FieldDefinitionId, FieldKey, Value, Weight, CreatedAt, UpdatedAt, IsDeleted)\n SELECT\n UPPER(SUBSTR(hex(randomblob(4)), 1, 8) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(6)), 1, 12)) AS Id,\n p.CredentialId AS ItemId,\n NULL AS FieldDefinitionId,\n 'login.password' AS FieldKey,\n p.Value AS Value,\n 0 AS Weight,\n p.UpdatedAt AS CreatedAt,\n p.UpdatedAt AS UpdatedAt,\n 0 AS IsDeleted\n FROM Passwords p\n INNER JOIN (\n SELECT CredentialId, MAX(UpdatedAt) AS MaxUpdated, MAX(Id) AS MaxId\n FROM Passwords\n WHERE IsDeleted = 0\n GROUP BY CredentialId\n ) pm ON p.CredentialId = pm.CredentialId AND p.UpdatedAt = pm.MaxUpdated AND p.Id = pm.MaxId\n WHERE p.IsDeleted = 0;\n \n\n\n INSERT INTO FieldValues (Id, ItemId, FieldDefinitionId, FieldKey, Value, Weight, CreatedAt, UpdatedAt, IsDeleted)\n SELECT\n UPPER(SUBSTR(hex(randomblob(4)), 1, 8) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(6)), 1, 12)) AS Id,\n c.Id AS ItemId,\n NULL AS FieldDefinitionId,\n 'login.email' AS FieldKey,\n a.Email AS Value,\n 0 AS Weight,\n a.UpdatedAt AS CreatedAt,\n a.UpdatedAt AS UpdatedAt,\n 0 AS IsDeleted\n FROM Credentials c\n INNER JOIN Aliases a ON a.Id = c.AliasId\n WHERE a.Email IS NOT NULL AND a.Email != '';\n \n\n\n INSERT INTO FieldValues (Id, ItemId, FieldDefinitionId, FieldKey, Value, Weight, CreatedAt, UpdatedAt, IsDeleted)\n SELECT\n UPPER(SUBSTR(hex(randomblob(4)), 1, 8) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(6)), 1, 12)) AS Id,\n c.Id AS ItemId,\n NULL AS FieldDefinitionId,\n 'alias.first_name' AS FieldKey,\n a.FirstName AS Value,\n 0 AS Weight,\n a.UpdatedAt AS CreatedAt,\n a.UpdatedAt AS UpdatedAt,\n 0 AS IsDeleted\n FROM Credentials c\n INNER JOIN Aliases a ON a.Id = c.AliasId\n WHERE a.FirstName IS NOT NULL AND a.FirstName != '';\n \n\n\n INSERT INTO FieldValues (Id, ItemId, FieldDefinitionId, FieldKey, Value, Weight, CreatedAt, UpdatedAt, IsDeleted)\n SELECT\n UPPER(SUBSTR(hex(randomblob(4)), 1, 8) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(6)), 1, 12)) AS Id,\n c.Id AS ItemId,\n NULL AS FieldDefinitionId,\n 'alias.last_name' AS FieldKey,\n a.LastName AS Value,\n 0 AS Weight,\n a.UpdatedAt AS CreatedAt,\n a.UpdatedAt AS UpdatedAt,\n 0 AS IsDeleted\n FROM Credentials c\n INNER JOIN Aliases a ON a.Id = c.AliasId\n WHERE a.LastName IS NOT NULL AND a.LastName != '';\n \n\n\n INSERT INTO FieldValues (Id, ItemId, FieldDefinitionId, FieldKey, Value, Weight, CreatedAt, UpdatedAt, IsDeleted)\n SELECT\n UPPER(SUBSTR(hex(randomblob(4)), 1, 8) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(6)), 1, 12)) AS Id,\n c.Id AS ItemId,\n NULL AS FieldDefinitionId,\n 'alias.gender' AS FieldKey,\n a.Gender AS Value,\n 0 AS Weight,\n a.UpdatedAt AS CreatedAt,\n a.UpdatedAt AS UpdatedAt,\n 0 AS IsDeleted\n FROM Credentials c\n INNER JOIN Aliases a ON a.Id = c.AliasId\n WHERE a.Gender IS NOT NULL AND a.Gender != '';\n \n\n\n INSERT INTO FieldValues (Id, ItemId, FieldDefinitionId, FieldKey, Value, Weight, CreatedAt, UpdatedAt, IsDeleted)\n SELECT\n UPPER(SUBSTR(hex(randomblob(4)), 1, 8) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(2)), 1, 4) || '-' ||\n SUBSTR(hex(randomblob(6)), 1, 12)) AS Id,\n c.Id AS ItemId,\n NULL AS FieldDefinitionId,\n 'alias.birthdate' AS FieldKey,\n SUBSTR(a.BirthDate, 1, 10) AS Value,\n 0 AS Weight,\n a.UpdatedAt AS CreatedAt,\n a.UpdatedAt AS UpdatedAt,\n 0 AS IsDeleted\n FROM Credentials c\n INNER JOIN Aliases a ON a.Id = c.AliasId\n WHERE a.BirthDate IS NOT NULL AND a.BirthDate != '' AND a.BirthDate NOT LIKE '0001-%';\n \n\nDROP TABLE \"Passwords\";\n\nDROP TABLE \"Credentials\";\n\nDROP TABLE \"Aliases\";\n\nDROP TABLE \"Services\";\n\nCREATE TABLE \"ef_temp_Attachments\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_Attachments\" PRIMARY KEY,\n \"Blob\" BLOB NOT NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"Filename\" TEXT NOT NULL,\n \"IsDeleted\" INTEGER NOT NULL,\n \"ItemId\" TEXT NOT NULL,\n \"UpdatedAt\" TEXT NOT NULL,\n CONSTRAINT \"FK_Attachments_Items_ItemId\" FOREIGN KEY (\"ItemId\") REFERENCES \"Items\" (\"Id\") ON DELETE CASCADE\n);\n\nINSERT INTO \"ef_temp_Attachments\" (\"Id\", \"Blob\", \"CreatedAt\", \"Filename\", \"IsDeleted\", \"ItemId\", \"UpdatedAt\")\nSELECT \"Id\", \"Blob\", \"CreatedAt\", \"Filename\", \"IsDeleted\", \"ItemId\", \"UpdatedAt\"\nFROM \"Attachments\";\n\nCREATE TABLE \"ef_temp_Passkeys\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_Passkeys\" PRIMARY KEY,\n \"AdditionalData\" BLOB NULL,\n \"CreatedAt\" TEXT NOT NULL,\n \"DisplayName\" TEXT NOT NULL,\n \"IsDeleted\" INTEGER NOT NULL,\n \"ItemId\" TEXT NOT NULL,\n \"PrfKey\" BLOB NULL,\n \"PrivateKey\" TEXT NOT NULL,\n \"PublicKey\" TEXT NOT NULL,\n \"RpId\" TEXT COLLATE NOCASE NOT NULL,\n \"UpdatedAt\" TEXT NOT NULL,\n \"UserHandle\" BLOB NOT NULL,\n CONSTRAINT \"FK_Passkeys_Items_ItemId\" FOREIGN KEY (\"ItemId\") REFERENCES \"Items\" (\"Id\") ON DELETE CASCADE\n);\n\nINSERT INTO \"ef_temp_Passkeys\" (\"Id\", \"AdditionalData\", \"CreatedAt\", \"DisplayName\", \"IsDeleted\", \"ItemId\", \"PrfKey\", \"PrivateKey\", \"PublicKey\", \"RpId\", \"UpdatedAt\", \"UserHandle\")\nSELECT \"Id\", \"AdditionalData\", \"CreatedAt\", \"DisplayName\", \"IsDeleted\", \"ItemId\", \"PrfKey\", \"PrivateKey\", \"PublicKey\", \"RpId\", \"UpdatedAt\", \"UserHandle\"\nFROM \"Passkeys\";\n\nCREATE TABLE \"ef_temp_TotpCodes\" (\n \"Id\" TEXT NOT NULL CONSTRAINT \"PK_TotpCodes\" PRIMARY KEY,\n \"CreatedAt\" TEXT NOT NULL,\n \"IsDeleted\" INTEGER NOT NULL,\n \"ItemId\" TEXT NOT NULL,\n \"Name\" TEXT NOT NULL,\n \"SecretKey\" TEXT NOT NULL,\n \"UpdatedAt\" TEXT NOT NULL,\n CONSTRAINT \"FK_TotpCodes_Items_ItemId\" FOREIGN KEY (\"ItemId\") REFERENCES \"Items\" (\"Id\") ON DELETE CASCADE\n);\n\nINSERT INTO \"ef_temp_TotpCodes\" (\"Id\", \"CreatedAt\", \"IsDeleted\", \"ItemId\", \"Name\", \"SecretKey\", \"UpdatedAt\")\nSELECT \"Id\", \"CreatedAt\", \"IsDeleted\", \"ItemId\", \"Name\", \"SecretKey\", \"UpdatedAt\"\nFROM \"TotpCodes\";\n\nCOMMIT;\n\nPRAGMA foreign_keys = 0;\n\nBEGIN TRANSACTION;\nDROP TABLE \"Attachments\";\n\nALTER TABLE \"ef_temp_Attachments\" RENAME TO \"Attachments\";\n\nDROP TABLE \"Passkeys\";\n\nALTER TABLE \"ef_temp_Passkeys\" RENAME TO \"Passkeys\";\n\nDROP TABLE \"TotpCodes\";\n\nALTER TABLE \"ef_temp_TotpCodes\" RENAME TO \"TotpCodes\";\n\nCOMMIT;\n\nPRAGMA foreign_keys = 1;\n\nBEGIN TRANSACTION;\nCREATE INDEX \"IX_Attachments_ItemId\" ON \"Attachments\" (\"ItemId\");\n\nCREATE INDEX \"IX_Passkeys_ItemId\" ON \"Passkeys\" (\"ItemId\");\n\nCREATE INDEX \"IX_Passkeys_RpId\" ON \"Passkeys\" (\"RpId\");\n\nCREATE INDEX \"IX_TotpCodes_ItemId\" ON \"TotpCodes\" (\"ItemId\");\n\nCOMMIT;\n\nINSERT INTO \"__EFMigrationsHistory\" (\"MigrationId\", \"ProductVersion\")\nVALUES ('20251213111207_1.7.0-FieldBasedDataModelUpdate', '9.0.4');\n\nBEGIN TRANSACTION;\nINSERT INTO \"__EFMigrationsHistory\" (\"MigrationId\", \"ProductVersion\")\nVALUES ('20260130221620_2.0.0-MajorVersionBump', '9.0.4');\n\nCOMMIT;\n"; /** * Individual migration SQL scripts * Auto-generated from EF Core migrations diff --git a/apps/server/AliasVault.Client/wwwroot/js/dist/core/vault/index.js b/apps/server/AliasVault.Client/wwwroot/js/dist/core/vault/index.js index e0802c5be..b8ea571cb 100644 --- a/apps/server/AliasVault.Client/wwwroot/js/dist/core/vault/index.js +++ b/apps/server/AliasVault.Client/wwwroot/js/dist/core/vault/index.js @@ -1296,6 +1296,12 @@ COMMIT; INSERT INTO "__EFMigrationsHistory" ("MigrationId", "ProductVersion") VALUES ('20251213111207_1.7.0-FieldBasedDataModelUpdate', '9.0.4'); + +BEGIN TRANSACTION; +INSERT INTO "__EFMigrationsHistory" ("MigrationId", "ProductVersion") +VALUES ('20260130221620_2.0.0-MajorVersionBump', '9.0.4'); + +COMMIT; `; var MIGRATION_SCRIPTS = { 1: `\uFEFFBEGIN TRANSACTION; @@ -2492,7 +2498,12 @@ CREATE INDEX "IX_TotpCodes_ItemId" ON "TotpCodes" ("ItemId"); COMMIT; INSERT INTO "__EFMigrationsHistory" ("MigrationId", "ProductVersion") -VALUES ('20251213111207_1.7.0-FieldBasedDataModelUpdate', '9.0.4');` +VALUES ('20251213111207_1.7.0-FieldBasedDataModelUpdate', '9.0.4');`, + 12: `\uFEFFBEGIN TRANSACTION; +INSERT INTO "__EFMigrationsHistory" ("MigrationId", "ProductVersion") +VALUES ('20260130221620_2.0.0-MajorVersionBump', '9.0.4'); + +COMMIT;` }; // src/sql/VaultVersions.ts @@ -2579,7 +2590,14 @@ var VAULT_VERSIONS = [ version: "1.7.0", description: "Update to Field-Based Data Model", releaseVersion: "0.26.0", - compatibleUpToVersion: "0.26.0" + compatibleUpToVersion: "0.25.0" + }, + { + revision: 13, + version: "2.0.0", + description: "Update to Field-Based Data Model", + releaseVersion: "0.26.1", + compatibleUpToVersion: "0.25.0" } ]; diff --git a/apps/server/AliasVault.Client/wwwroot/js/dist/core/vault/index.mjs b/apps/server/AliasVault.Client/wwwroot/js/dist/core/vault/index.mjs index 8c4d5fa37..d5e02f646 100644 --- a/apps/server/AliasVault.Client/wwwroot/js/dist/core/vault/index.mjs +++ b/apps/server/AliasVault.Client/wwwroot/js/dist/core/vault/index.mjs @@ -1264,6 +1264,12 @@ COMMIT; INSERT INTO "__EFMigrationsHistory" ("MigrationId", "ProductVersion") VALUES ('20251213111207_1.7.0-FieldBasedDataModelUpdate', '9.0.4'); + +BEGIN TRANSACTION; +INSERT INTO "__EFMigrationsHistory" ("MigrationId", "ProductVersion") +VALUES ('20260130221620_2.0.0-MajorVersionBump', '9.0.4'); + +COMMIT; `; var MIGRATION_SCRIPTS = { 1: `\uFEFFBEGIN TRANSACTION; @@ -2460,7 +2466,12 @@ CREATE INDEX "IX_TotpCodes_ItemId" ON "TotpCodes" ("ItemId"); COMMIT; INSERT INTO "__EFMigrationsHistory" ("MigrationId", "ProductVersion") -VALUES ('20251213111207_1.7.0-FieldBasedDataModelUpdate', '9.0.4');` +VALUES ('20251213111207_1.7.0-FieldBasedDataModelUpdate', '9.0.4');`, + 12: `\uFEFFBEGIN TRANSACTION; +INSERT INTO "__EFMigrationsHistory" ("MigrationId", "ProductVersion") +VALUES ('20260130221620_2.0.0-MajorVersionBump', '9.0.4'); + +COMMIT;` }; // src/sql/VaultVersions.ts @@ -2547,7 +2558,14 @@ var VAULT_VERSIONS = [ version: "1.7.0", description: "Update to Field-Based Data Model", releaseVersion: "0.26.0", - compatibleUpToVersion: "0.26.0" + compatibleUpToVersion: "0.25.0" + }, + { + revision: 13, + version: "2.0.0", + description: "Update to Field-Based Data Model", + releaseVersion: "0.26.1", + compatibleUpToVersion: "0.25.0" } ]; diff --git a/apps/server/Databases/AliasClientDb/Migrations/20260130221620_2.0.0-MajorVersionBump.Designer.cs b/apps/server/Databases/AliasClientDb/Migrations/20260130221620_2.0.0-MajorVersionBump.Designer.cs new file mode 100644 index 000000000..378ca882a --- /dev/null +++ b/apps/server/Databases/AliasClientDb/Migrations/20260130221620_2.0.0-MajorVersionBump.Designer.cs @@ -0,0 +1,675 @@ +// +using System; +using AliasClientDb; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; + +#nullable disable + +namespace AliasClientDb.Migrations +{ + [DbContext(typeof(AliasClientDbContext))] + [Migration("20260130221620_2.0.0-MajorVersionBump")] + partial class _200MajorVersionBump + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "9.0.4") + .HasAnnotation("Proxies:ChangeTracking", false) + .HasAnnotation("Proxies:CheckEquality", false) + .HasAnnotation("Proxies:LazyLoading", true); + + modelBuilder.Entity("AliasClientDb.Attachment", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("TEXT"); + + b.Property("Blob") + .IsRequired() + .HasColumnType("BLOB"); + + b.Property("CreatedAt") + .HasColumnType("TEXT"); + + b.Property("Filename") + .IsRequired() + .HasMaxLength(255) + .HasColumnType("TEXT"); + + b.Property("IsDeleted") + .HasColumnType("INTEGER"); + + b.Property("ItemId") + .HasColumnType("TEXT"); + + b.Property("UpdatedAt") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("ItemId"); + + b.ToTable("Attachments"); + }); + + modelBuilder.Entity("AliasClientDb.EncryptionKey", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("TEXT"); + + b.Property("CreatedAt") + .HasColumnType("TEXT"); + + b.Property("IsDeleted") + .HasColumnType("INTEGER"); + + b.Property("IsPrimary") + .HasColumnType("INTEGER"); + + b.Property("PrivateKey") + .IsRequired() + .HasMaxLength(2000) + .HasColumnType("TEXT"); + + b.Property("PublicKey") + .IsRequired() + .HasMaxLength(2000) + .HasColumnType("TEXT"); + + b.Property("UpdatedAt") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.ToTable("EncryptionKeys"); + }); + + modelBuilder.Entity("AliasClientDb.FieldDefinition", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("TEXT"); + + b.Property("ApplicableToTypes") + .HasColumnType("TEXT"); + + b.Property("CreatedAt") + .HasColumnType("TEXT"); + + b.Property("EnableHistory") + .HasColumnType("INTEGER"); + + b.Property("FieldType") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("TEXT"); + + b.Property("IsDeleted") + .HasColumnType("INTEGER"); + + b.Property("IsHidden") + .HasColumnType("INTEGER"); + + b.Property("IsMultiValue") + .HasColumnType("INTEGER"); + + b.Property("Label") + .IsRequired() + .HasMaxLength(255) + .HasColumnType("TEXT"); + + b.Property("UpdatedAt") + .HasColumnType("TEXT"); + + b.Property("Weight") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.ToTable("FieldDefinitions"); + }); + + modelBuilder.Entity("AliasClientDb.FieldHistory", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("TEXT"); + + b.Property("ChangedAt") + .HasColumnType("TEXT"); + + b.Property("CreatedAt") + .HasColumnType("TEXT"); + + b.Property("FieldDefinitionId") + .HasColumnType("TEXT"); + + b.Property("FieldKey") + .HasMaxLength(100) + .HasColumnType("TEXT"); + + b.Property("IsDeleted") + .HasColumnType("INTEGER"); + + b.Property("ItemId") + .HasColumnType("TEXT"); + + b.Property("UpdatedAt") + .HasColumnType("TEXT"); + + b.Property("ValueSnapshot") + .IsRequired() + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("FieldDefinitionId"); + + b.HasIndex("ItemId"); + + b.ToTable("FieldHistories"); + }); + + modelBuilder.Entity("AliasClientDb.FieldValue", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("TEXT"); + + b.Property("CreatedAt") + .HasColumnType("TEXT"); + + b.Property("FieldDefinitionId") + .HasColumnType("TEXT"); + + b.Property("FieldKey") + .HasMaxLength(100) + .HasColumnType("TEXT"); + + b.Property("IsDeleted") + .HasColumnType("INTEGER"); + + b.Property("ItemId") + .HasColumnType("TEXT"); + + b.Property("UpdatedAt") + .HasColumnType("TEXT"); + + b.Property("Value") + .HasColumnType("TEXT"); + + b.Property("Weight") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("FieldDefinitionId"); + + b.HasIndex("FieldKey"); + + b.HasIndex("ItemId"); + + b.HasIndex("ItemId", "FieldKey"); + + b.HasIndex("ItemId", "FieldDefinitionId", "Weight"); + + b.ToTable("FieldValues"); + }); + + modelBuilder.Entity("AliasClientDb.Folder", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("TEXT"); + + b.Property("CreatedAt") + .HasColumnType("TEXT"); + + b.Property("IsDeleted") + .HasColumnType("INTEGER"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(255) + .HasColumnType("TEXT"); + + b.Property("ParentFolderId") + .HasColumnType("TEXT"); + + b.Property("UpdatedAt") + .HasColumnType("TEXT"); + + b.Property("Weight") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("ParentFolderId"); + + b.ToTable("Folders"); + }); + + modelBuilder.Entity("AliasClientDb.Item", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("TEXT"); + + b.Property("CreatedAt") + .HasColumnType("TEXT"); + + b.Property("DeletedAt") + .HasColumnType("TEXT"); + + b.Property("FolderId") + .HasColumnType("TEXT"); + + b.Property("IsDeleted") + .HasColumnType("INTEGER"); + + b.Property("ItemType") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("TEXT"); + + b.Property("LogoId") + .HasColumnType("TEXT"); + + b.Property("Name") + .HasMaxLength(255) + .HasColumnType("TEXT"); + + b.Property("UpdatedAt") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("FolderId"); + + b.HasIndex("LogoId"); + + b.ToTable("Items"); + }); + + modelBuilder.Entity("AliasClientDb.ItemTag", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("TEXT"); + + b.Property("CreatedAt") + .HasColumnType("TEXT"); + + b.Property("IsDeleted") + .HasColumnType("INTEGER"); + + b.Property("ItemId") + .HasColumnType("TEXT"); + + b.Property("TagId") + .HasColumnType("TEXT"); + + b.Property("UpdatedAt") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("ItemId"); + + b.HasIndex("TagId"); + + b.HasIndex("ItemId", "TagId") + .IsUnique(); + + b.ToTable("ItemTags"); + }); + + modelBuilder.Entity("AliasClientDb.Logo", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("TEXT"); + + b.Property("CreatedAt") + .HasColumnType("TEXT"); + + b.Property("FetchedAt") + .HasColumnType("TEXT"); + + b.Property("FileData") + .HasColumnType("BLOB"); + + b.Property("IsDeleted") + .HasColumnType("INTEGER"); + + b.Property("MimeType") + .HasMaxLength(100) + .HasColumnType("TEXT"); + + b.Property("Source") + .IsRequired() + .HasMaxLength(255) + .HasColumnType("TEXT"); + + b.Property("UpdatedAt") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("Source") + .IsUnique(); + + b.ToTable("Logos"); + }); + + modelBuilder.Entity("AliasClientDb.Passkey", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("TEXT"); + + b.Property("AdditionalData") + .HasColumnType("BLOB"); + + b.Property("CreatedAt") + .HasColumnType("TEXT"); + + b.Property("DisplayName") + .IsRequired() + .HasMaxLength(255) + .HasColumnType("TEXT"); + + b.Property("IsDeleted") + .HasColumnType("INTEGER"); + + b.Property("ItemId") + .HasColumnType("TEXT"); + + b.Property("PrfKey") + .HasMaxLength(64) + .HasColumnType("BLOB"); + + b.Property("PrivateKey") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("PublicKey") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("RpId") + .IsRequired() + .HasMaxLength(255) + .HasColumnType("TEXT") + .UseCollation("NOCASE"); + + b.Property("UpdatedAt") + .HasColumnType("TEXT"); + + b.Property("UserHandle") + .IsRequired() + .HasColumnType("BLOB"); + + b.HasKey("Id"); + + b.HasIndex("ItemId"); + + b.HasIndex("RpId"); + + b.ToTable("Passkeys"); + }); + + modelBuilder.Entity("AliasClientDb.Setting", b => + { + b.Property("Key") + .HasMaxLength(255) + .HasColumnType("TEXT"); + + b.Property("CreatedAt") + .HasColumnType("TEXT"); + + b.Property("IsDeleted") + .HasColumnType("INTEGER"); + + b.Property("UpdatedAt") + .HasColumnType("TEXT"); + + b.Property("Value") + .HasColumnType("TEXT"); + + b.HasKey("Key"); + + b.ToTable("Settings"); + }); + + modelBuilder.Entity("AliasClientDb.Tag", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("TEXT"); + + b.Property("Color") + .HasMaxLength(50) + .HasColumnType("TEXT"); + + b.Property("CreatedAt") + .HasColumnType("TEXT"); + + b.Property("DisplayOrder") + .HasColumnType("INTEGER"); + + b.Property("IsDeleted") + .HasColumnType("INTEGER"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(255) + .HasColumnType("TEXT"); + + b.Property("UpdatedAt") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("Name"); + + b.ToTable("Tags"); + }); + + modelBuilder.Entity("AliasClientDb.TotpCode", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("TEXT"); + + b.Property("CreatedAt") + .HasColumnType("TEXT"); + + b.Property("IsDeleted") + .HasColumnType("INTEGER"); + + b.Property("ItemId") + .HasColumnType("TEXT"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(255) + .HasColumnType("TEXT"); + + b.Property("SecretKey") + .IsRequired() + .HasMaxLength(255) + .HasColumnType("TEXT"); + + b.Property("UpdatedAt") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("ItemId"); + + b.ToTable("TotpCodes"); + }); + + modelBuilder.Entity("AliasClientDb.Attachment", b => + { + b.HasOne("AliasClientDb.Item", "Item") + .WithMany("Attachments") + .HasForeignKey("ItemId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Item"); + }); + + modelBuilder.Entity("AliasClientDb.FieldHistory", b => + { + b.HasOne("AliasClientDb.FieldDefinition", "FieldDefinition") + .WithMany("FieldHistories") + .HasForeignKey("FieldDefinitionId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("AliasClientDb.Item", "Item") + .WithMany() + .HasForeignKey("ItemId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("FieldDefinition"); + + b.Navigation("Item"); + }); + + modelBuilder.Entity("AliasClientDb.FieldValue", b => + { + b.HasOne("AliasClientDb.FieldDefinition", "FieldDefinition") + .WithMany("FieldValues") + .HasForeignKey("FieldDefinitionId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("AliasClientDb.Item", "Item") + .WithMany("FieldValues") + .HasForeignKey("ItemId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("FieldDefinition"); + + b.Navigation("Item"); + }); + + modelBuilder.Entity("AliasClientDb.Folder", b => + { + b.HasOne("AliasClientDb.Folder", "ParentFolder") + .WithMany("ChildFolders") + .HasForeignKey("ParentFolderId") + .OnDelete(DeleteBehavior.Cascade); + + b.Navigation("ParentFolder"); + }); + + modelBuilder.Entity("AliasClientDb.Item", b => + { + b.HasOne("AliasClientDb.Folder", "Folder") + .WithMany("Items") + .HasForeignKey("FolderId") + .OnDelete(DeleteBehavior.SetNull); + + b.HasOne("AliasClientDb.Logo", "Logo") + .WithMany("Items") + .HasForeignKey("LogoId") + .OnDelete(DeleteBehavior.SetNull); + + b.Navigation("Folder"); + + b.Navigation("Logo"); + }); + + modelBuilder.Entity("AliasClientDb.ItemTag", b => + { + b.HasOne("AliasClientDb.Item", "Item") + .WithMany("ItemTags") + .HasForeignKey("ItemId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("AliasClientDb.Tag", "Tag") + .WithMany("ItemTags") + .HasForeignKey("TagId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Item"); + + b.Navigation("Tag"); + }); + + modelBuilder.Entity("AliasClientDb.Passkey", b => + { + b.HasOne("AliasClientDb.Item", "Item") + .WithMany("Passkeys") + .HasForeignKey("ItemId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Item"); + }); + + modelBuilder.Entity("AliasClientDb.TotpCode", b => + { + b.HasOne("AliasClientDb.Item", "Item") + .WithMany("TotpCodes") + .HasForeignKey("ItemId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Item"); + }); + + modelBuilder.Entity("AliasClientDb.FieldDefinition", b => + { + b.Navigation("FieldHistories"); + + b.Navigation("FieldValues"); + }); + + modelBuilder.Entity("AliasClientDb.Folder", b => + { + b.Navigation("ChildFolders"); + + b.Navigation("Items"); + }); + + modelBuilder.Entity("AliasClientDb.Item", b => + { + b.Navigation("Attachments"); + + b.Navigation("FieldValues"); + + b.Navigation("ItemTags"); + + b.Navigation("Passkeys"); + + b.Navigation("TotpCodes"); + }); + + modelBuilder.Entity("AliasClientDb.Logo", b => + { + b.Navigation("Items"); + }); + + modelBuilder.Entity("AliasClientDb.Tag", b => + { + b.Navigation("ItemTags"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/apps/server/Databases/AliasClientDb/Migrations/20260130221620_2.0.0-MajorVersionBump.cs b/apps/server/Databases/AliasClientDb/Migrations/20260130221620_2.0.0-MajorVersionBump.cs new file mode 100644 index 000000000..bfd832ec0 --- /dev/null +++ b/apps/server/Databases/AliasClientDb/Migrations/20260130221620_2.0.0-MajorVersionBump.cs @@ -0,0 +1,23 @@ +// +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace AliasClientDb.Migrations +{ + /// + public partial class _200MajorVersionBump : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + + } + } +} diff --git a/apps/server/Databases/AliasClientDb/Scripts/MigrationSql/000_FullSchema.sql b/apps/server/Databases/AliasClientDb/Scripts/MigrationSql/000_FullSchema.sql index 2be319b50..98dae315b 100644 --- a/apps/server/Databases/AliasClientDb/Scripts/MigrationSql/000_FullSchema.sql +++ b/apps/server/Databases/AliasClientDb/Scripts/MigrationSql/000_FullSchema.sql @@ -1259,3 +1259,9 @@ COMMIT; INSERT INTO "__EFMigrationsHistory" ("MigrationId", "ProductVersion") VALUES ('20251213111207_1.7.0-FieldBasedDataModelUpdate', '9.0.4'); +BEGIN TRANSACTION; +INSERT INTO "__EFMigrationsHistory" ("MigrationId", "ProductVersion") +VALUES ('20260130221620_2.0.0-MajorVersionBump', '9.0.4'); + +COMMIT; + diff --git a/apps/server/Databases/AliasClientDb/Scripts/MigrationSql/012_20251213111207_1.7.0-FieldBasedDataModelUpdate_to_20260130221620_2.0.0-MajorVersionBump.sql b/apps/server/Databases/AliasClientDb/Scripts/MigrationSql/012_20251213111207_1.7.0-FieldBasedDataModelUpdate_to_20260130221620_2.0.0-MajorVersionBump.sql new file mode 100644 index 000000000..b1931ef1d --- /dev/null +++ b/apps/server/Databases/AliasClientDb/Scripts/MigrationSql/012_20251213111207_1.7.0-FieldBasedDataModelUpdate_to_20260130221620_2.0.0-MajorVersionBump.sql @@ -0,0 +1,6 @@ +BEGIN TRANSACTION; +INSERT INTO "__EFMigrationsHistory" ("MigrationId", "ProductVersion") +VALUES ('20260130221620_2.0.0-MajorVersionBump', '9.0.4'); + +COMMIT; + diff --git a/core/vault/src/sql/SqlConstants.ts b/core/vault/src/sql/SqlConstants.ts index c86efe30b..42552106b 100644 --- a/core/vault/src/sql/SqlConstants.ts +++ b/core/vault/src/sql/SqlConstants.ts @@ -1265,6 +1265,12 @@ COMMIT; INSERT INTO "__EFMigrationsHistory" ("MigrationId", "ProductVersion") VALUES ('20251213111207_1.7.0-FieldBasedDataModelUpdate', '9.0.4'); + +BEGIN TRANSACTION; +INSERT INTO "__EFMigrationsHistory" ("MigrationId", "ProductVersion") +VALUES ('20260130221620_2.0.0-MajorVersionBump', '9.0.4'); + +COMMIT; `; /** * Individual migration SQL scripts @@ -2466,4 +2472,9 @@ COMMIT; INSERT INTO "__EFMigrationsHistory" ("MigrationId", "ProductVersion") VALUES ('20251213111207_1.7.0-FieldBasedDataModelUpdate', '9.0.4');`, + 12: `BEGIN TRANSACTION; +INSERT INTO "__EFMigrationsHistory" ("MigrationId", "ProductVersion") +VALUES ('20260130221620_2.0.0-MajorVersionBump', '9.0.4'); + +COMMIT;`, }; diff --git a/core/vault/src/sql/VaultVersions.ts b/core/vault/src/sql/VaultVersions.ts index aae4c50a7..ad7800388 100644 --- a/core/vault/src/sql/VaultVersions.ts +++ b/core/vault/src/sql/VaultVersions.ts @@ -93,6 +93,13 @@ export const VAULT_VERSIONS: VaultVersion[] = [ version: '1.7.0', description: 'Update to Field-Based Data Model', releaseVersion: '0.26.0', - compatibleUpToVersion: '0.26.0', + compatibleUpToVersion: '0.25.0', + }, + { + revision: 13, + version: '2.0.0', + description: 'Update to Field-Based Data Model', + releaseVersion: '0.26.1', + compatibleUpToVersion: '0.25.0', }, ];