diff --git a/.github/workflows/browser-extension-build.yml b/.github/workflows/browser-extension-build.yml
index 5925d8e29..7da8288c3 100644
--- a/.github/workflows/browser-extension-build.yml
+++ b/.github/workflows/browser-extension-build.yml
@@ -22,20 +22,20 @@ jobs:
with:
node-version: '20'
- - name: Build and distribute shared libraries
+ - name: Build and distribute core libraries
run: |
- cd ./shared
+ cd ./core
chmod +x build-and-distribute.sh
./build-and-distribute.sh
- - name: Verify shared library distribution
+ - name: Verify core library distribution
run: |
# Check if files exist and were recently modified
TARGET_DIRS=(
- "apps/browser-extension/src/utils/dist/shared/identity-generator"
- "apps/browser-extension/src/utils/dist/shared/password-generator"
- "apps/browser-extension/src/utils/dist/shared/models"
- "apps/browser-extension/src/utils/dist/shared/vault-sql"
+ "apps/browser-extension/src/utils/dist/core/identity-generator"
+ "apps/browser-extension/src/utils/dist/core/password-generator"
+ "apps/browser-extension/src/utils/dist/core/models"
+ "apps/browser-extension/src/utils/dist/core/vault"
)
for dir in "${TARGET_DIRS[@]}"; do
diff --git a/.github/workflows/mobile-app-build.yml b/.github/workflows/mobile-app-build.yml
index b0326f725..4f090778d 100644
--- a/.github/workflows/mobile-app-build.yml
+++ b/.github/workflows/mobile-app-build.yml
@@ -43,20 +43,20 @@ jobs:
cache: 'npm'
cache-dependency-path: apps/mobile-app/package-lock.json
- - name: Build and distribute shared libraries
+ - name: Build and distribute core libraries
run: |
- cd ../../shared
+ cd ../../core
chmod +x build-and-distribute.sh
./build-and-distribute.sh
- - name: Verify shared library distribution
+ - name: Verify core library distribution
run: |
# Check if files exist and were recently modified
TARGET_DIRS=(
- "utils/dist/shared/identity-generator"
- "utils/dist/shared/password-generator"
- "utils/dist/shared/models"
- "utils/dist/shared/vault-sql"
+ "utils/dist/core/identity-generator"
+ "utils/dist/core/password-generator"
+ "utils/dist/core/models"
+ "utils/dist/core/vault"
)
for dir in "${TARGET_DIRS[@]}"; do
diff --git a/.gitignore b/.gitignore
index e1120f9fd..da99ab99b 100644
--- a/.gitignore
+++ b/.gitignore
@@ -435,20 +435,20 @@ temp
# Safari extension build files
apps/browser-extension/safari-xcode/AliasVault/build
-# Rust core binaries (built by ./build.sh in shared/rust-core)
+# Rust core binaries (built by ./build.sh in core/rust)
# These are platform-specific and must be built locally or by CI
-shared/rust-core/dist/
-shared/rust-core/target/
+core/rust/dist/
+core/rust/target/
-# Browser extension WASM (built by: cd shared/rust-core && ./build.sh --browser)
-apps/browser-extension/src/utils/dist/shared/rust-core
+# Browser extension WASM (built by: cd core/rust && ./build.sh --browser)
+apps/browser-extension/src/utils/dist/core/rust
-# iOS Swift bindings (built by: cd shared/rust-core && ./build.sh --ios)
+# iOS Swift bindings (built by: cd core/rust && ./build.sh --ios)
apps/mobile-app/ios/AliasVaultCore/
-# Android Kotlin bindings (built by: cd shared/rust-core && ./build.sh --android)
+# Android Kotlin bindings (built by: cd core/rust && ./build.sh --android)
apps/mobile-app/android/app/src/main/java/com/aliasvault/core/
apps/mobile-app/android/app/src/main/jniLibs/
-# Server .NET bindings (built by: cd shared/rust-core && ./build.sh --server)
+# Server .NET bindings (built by: cd core/rust && ./build.sh --server)
apps/server/Utilities/AliasVault.RustCore/
diff --git a/.vscode/AliasVault.code-workspace b/.vscode/AliasVault.code-workspace
index eec6c1292..48ac8f967 100644
--- a/.vscode/AliasVault.code-workspace
+++ b/.vscode/AliasVault.code-workspace
@@ -20,7 +20,7 @@
"path": "../docs"
},
{
- "path": "../shared"
+ "path": "../core"
}
],
"settings": {
diff --git a/apps/browser-extension/src/entrypoints/background.ts b/apps/browser-extension/src/entrypoints/background.ts
index 35abe7311..229049e4c 100644
--- a/apps/browser-extension/src/entrypoints/background.ts
+++ b/apps/browser-extension/src/entrypoints/background.ts
@@ -12,7 +12,7 @@ import { handleOpenPopup, handlePopupWithCredential, handleOpenPopupCreateCreden
import { handleCheckAuthStatus, handleClearPersistedFormValues, handleClearVault, handleLockVault, handleCreateIdentity, handleGetCredentials, handleGetDefaultEmailDomain, handleGetDefaultIdentitySettings, handleGetEncryptionKey, handleGetEncryptionKeyDerivationParams, handleGetPasswordSettings, handleGetPersistedFormValues, handleGetVault, handlePersistFormValues, handleStoreEncryptionKey, handleStoreEncryptionKeyDerivationParams, handleStoreVaultMetadata, handleSyncVault, handleUploadVault, handleGetOfflineMode, handleSetOfflineMode, handleGetEncryptedVault, handleStoreEncryptedVault, handleGetHasPendingSync, handleSetHasPendingSync } from '@/entrypoints/background/VaultMessageHandler';
import { GLOBAL_CONTEXT_MENU_ENABLED_KEY } from '@/utils/Constants';
-import { EncryptionKeyDerivationParams } from "@/utils/dist/shared/models/metadata";
+import { EncryptionKeyDerivationParams } from "@/utils/dist/core/models/metadata";
import { defineBackground, storage, browser } from '#imports';
diff --git a/apps/browser-extension/src/entrypoints/background/ContextMenu.ts b/apps/browser-extension/src/entrypoints/background/ContextMenu.ts
index a3e479eee..2d08c134e 100644
--- a/apps/browser-extension/src/entrypoints/background/ContextMenu.ts
+++ b/apps/browser-extension/src/entrypoints/background/ContextMenu.ts
@@ -1,7 +1,7 @@
import { type Browser } from '@wxt-dev/browser';
import { sendMessage } from 'webext-bridge/background';
-import { PasswordGenerator } from '@/utils/dist/shared/password-generator';
+import { PasswordGenerator } from '@/utils/dist/core/password-generator';
import { t } from '@/i18n/StandaloneI18n';
diff --git a/apps/browser-extension/src/entrypoints/background/VaultMessageHandler.ts b/apps/browser-extension/src/entrypoints/background/VaultMessageHandler.ts
index 4edec18d3..7e8d9d5f1 100644
--- a/apps/browser-extension/src/entrypoints/background/VaultMessageHandler.ts
+++ b/apps/browser-extension/src/entrypoints/background/VaultMessageHandler.ts
@@ -1,8 +1,8 @@
/* eslint-disable @typescript-eslint/no-explicit-any */
import { storage } from 'wxt/utils/storage';
-import type { EncryptionKeyDerivationParams } from '@/utils/dist/shared/models/metadata';
-import type { Vault, VaultResponse, VaultPostResponse } from '@/utils/dist/shared/models/webapi';
+import type { EncryptionKeyDerivationParams } from '@/utils/dist/core/models/metadata';
+import type { Vault, VaultResponse, VaultPostResponse } from '@/utils/dist/core/models/webapi';
import { EncryptionUtility } from '@/utils/EncryptionUtility';
import { SqliteClient } from '@/utils/SqliteClient';
import { VaultVersionIncompatibleError } from '@/utils/types/errors/VaultVersionIncompatibleError';
diff --git a/apps/browser-extension/src/entrypoints/contentScript/Form.ts b/apps/browser-extension/src/entrypoints/contentScript/Form.ts
index 35867e503..1c3b10736 100644
--- a/apps/browser-extension/src/entrypoints/contentScript/Form.ts
+++ b/apps/browser-extension/src/entrypoints/contentScript/Form.ts
@@ -2,7 +2,7 @@ import { sendMessage } from 'webext-bridge/content-script';
import { openAutofillPopup } from '@/entrypoints/contentScript/Popup';
-import type { Credential } from '@/utils/dist/shared/models/vault';
+import type { Credential } from '@/utils/dist/core/models/vault';
import { FormDetector } from '@/utils/formDetector/FormDetector';
import { FormFiller } from '@/utils/formDetector/FormFiller';
import { ClickValidator } from '@/utils/security/ClickValidator';
diff --git a/apps/browser-extension/src/entrypoints/contentScript/Popup.ts b/apps/browser-extension/src/entrypoints/contentScript/Popup.ts
index 53faa464e..a1495b739 100644
--- a/apps/browser-extension/src/entrypoints/contentScript/Popup.ts
+++ b/apps/browser-extension/src/entrypoints/contentScript/Popup.ts
@@ -4,9 +4,9 @@ import { fillCredential } from '@/entrypoints/contentScript/Form';
import { DISABLED_SITES_KEY, TEMPORARY_DISABLED_SITES_KEY, GLOBAL_AUTOFILL_POPUP_ENABLED_KEY, VAULT_LOCKED_DISMISS_UNTIL_KEY, AUTOFILL_MATCHING_MODE_KEY, CUSTOM_EMAIL_HISTORY_KEY, CUSTOM_USERNAME_HISTORY_KEY } from '@/utils/Constants';
import { AutofillMatchingMode } from '@/utils/credentialMatcher/CredentialMatcher';
-import { CreateIdentityGenerator } from '@/utils/dist/shared/identity-generator';
-import type { Credential } from '@/utils/dist/shared/models/vault';
-import { CreatePasswordGenerator, PasswordGenerator, PasswordSettings } from '@/utils/dist/shared/password-generator';
+import { CreateIdentityGenerator } from '@/utils/dist/core/identity-generator';
+import type { Credential } from '@/utils/dist/core/models/vault';
+import { CreatePasswordGenerator, PasswordGenerator, PasswordSettings } from '@/utils/dist/core/password-generator';
import { ClickValidator } from '@/utils/security/ClickValidator';
import { ServiceDetectionUtility } from '@/utils/serviceDetection/ServiceDetectionUtility';
import { SqliteClient } from '@/utils/SqliteClient';
diff --git a/apps/browser-extension/src/entrypoints/popup/components/Credentials/CredentialCard.tsx b/apps/browser-extension/src/entrypoints/popup/components/Credentials/CredentialCard.tsx
index 67b40d714..b93877866 100644
--- a/apps/browser-extension/src/entrypoints/popup/components/Credentials/CredentialCard.tsx
+++ b/apps/browser-extension/src/entrypoints/popup/components/Credentials/CredentialCard.tsx
@@ -1,7 +1,7 @@
import React from 'react';
import { useNavigate } from 'react-router-dom';
-import type { Credential } from '@/utils/dist/shared/models/vault';
+import type { Credential } from '@/utils/dist/core/models/vault';
import SqliteClient from '@/utils/SqliteClient';
type CredentialCardProps = {
diff --git a/apps/browser-extension/src/entrypoints/popup/components/Credentials/Details/AliasBlock.tsx b/apps/browser-extension/src/entrypoints/popup/components/Credentials/Details/AliasBlock.tsx
index 09b7ae658..d6a63f31a 100644
--- a/apps/browser-extension/src/entrypoints/popup/components/Credentials/Details/AliasBlock.tsx
+++ b/apps/browser-extension/src/entrypoints/popup/components/Credentials/Details/AliasBlock.tsx
@@ -3,8 +3,8 @@ import { useTranslation } from 'react-i18next';
import { FormInputCopyToClipboard } from '@/entrypoints/popup/components/Forms/FormInputCopyToClipboard';
-import { IdentityHelperUtils } from '@/utils/dist/shared/identity-generator';
-import type { Credential } from '@/utils/dist/shared/models/vault';
+import { IdentityHelperUtils } from '@/utils/dist/core/identity-generator';
+import type { Credential } from '@/utils/dist/core/models/vault';
type AliasBlockProps = {
credential: Credential;
diff --git a/apps/browser-extension/src/entrypoints/popup/components/Credentials/Details/AttachmentBlock.tsx b/apps/browser-extension/src/entrypoints/popup/components/Credentials/Details/AttachmentBlock.tsx
index 44658a10b..2ce21b7c4 100644
--- a/apps/browser-extension/src/entrypoints/popup/components/Credentials/Details/AttachmentBlock.tsx
+++ b/apps/browser-extension/src/entrypoints/popup/components/Credentials/Details/AttachmentBlock.tsx
@@ -3,7 +3,7 @@ import { useTranslation } from 'react-i18next';
import { useDb } from '@/entrypoints/popup/context/DbContext';
-import type { Attachment } from '@/utils/dist/shared/models/vault';
+import type { Attachment } from '@/utils/dist/core/models/vault';
type AttachmentBlockProps = {
credentialId?: string;
diff --git a/apps/browser-extension/src/entrypoints/popup/components/Credentials/Details/AttachmentUploader.tsx b/apps/browser-extension/src/entrypoints/popup/components/Credentials/Details/AttachmentUploader.tsx
index 9dc597c68..e88a7a45a 100644
--- a/apps/browser-extension/src/entrypoints/popup/components/Credentials/Details/AttachmentUploader.tsx
+++ b/apps/browser-extension/src/entrypoints/popup/components/Credentials/Details/AttachmentUploader.tsx
@@ -1,7 +1,7 @@
import React, { useState } from 'react';
import { useTranslation } from 'react-i18next';
-import type { Attachment } from '@/utils/dist/shared/models/vault';
+import type { Attachment } from '@/utils/dist/core/models/vault';
type AttachmentUploaderProps = {
attachments: Attachment[];
diff --git a/apps/browser-extension/src/entrypoints/popup/components/Credentials/Details/FieldBlock.tsx b/apps/browser-extension/src/entrypoints/popup/components/Credentials/Details/FieldBlock.tsx
index 5da7b72a3..55fc45c2b 100644
--- a/apps/browser-extension/src/entrypoints/popup/components/Credentials/Details/FieldBlock.tsx
+++ b/apps/browser-extension/src/entrypoints/popup/components/Credentials/Details/FieldBlock.tsx
@@ -4,8 +4,8 @@ import { useTranslation } from 'react-i18next';
import { FormInputCopyToClipboard } from '@/entrypoints/popup/components/Forms/FormInputCopyToClipboard';
import { useDb } from '@/entrypoints/popup/context/DbContext';
-import type { ItemField } from '@/utils/dist/shared/models/vault';
-import { getSystemField } from '@/utils/dist/shared/models/vault';
+import type { ItemField } from '@/utils/dist/core/models/vault';
+import { getSystemField } from '@/utils/dist/core/models/vault';
import FieldHistoryModal from './FieldHistoryModal';
diff --git a/apps/browser-extension/src/entrypoints/popup/components/Credentials/Details/FieldHistoryModal.tsx b/apps/browser-extension/src/entrypoints/popup/components/Credentials/Details/FieldHistoryModal.tsx
index e7c7e2012..156017f18 100644
--- a/apps/browser-extension/src/entrypoints/popup/components/Credentials/Details/FieldHistoryModal.tsx
+++ b/apps/browser-extension/src/entrypoints/popup/components/Credentials/Details/FieldHistoryModal.tsx
@@ -3,7 +3,7 @@ import { useTranslation } from 'react-i18next';
import { useDb } from '@/entrypoints/popup/context/DbContext';
-import type { FieldHistory, FieldType } from '@/utils/dist/shared/models/vault';
+import type { FieldHistory, FieldType } from '@/utils/dist/core/models/vault';
type FieldHistoryModalProps = {
isOpen: boolean;
diff --git a/apps/browser-extension/src/entrypoints/popup/components/Credentials/Details/HeaderBlock.tsx b/apps/browser-extension/src/entrypoints/popup/components/Credentials/Details/HeaderBlock.tsx
index 8d3bcb89c..a1adab2a9 100644
--- a/apps/browser-extension/src/entrypoints/popup/components/Credentials/Details/HeaderBlock.tsx
+++ b/apps/browser-extension/src/entrypoints/popup/components/Credentials/Details/HeaderBlock.tsx
@@ -1,6 +1,6 @@
import React from 'react';
-import type { Credential } from '@/utils/dist/shared/models/vault';
+import type { Credential } from '@/utils/dist/core/models/vault';
import SqliteClient from '@/utils/SqliteClient';
type HeaderBlockProps = {
diff --git a/apps/browser-extension/src/entrypoints/popup/components/Credentials/Details/LoginCredentialsBlock.tsx b/apps/browser-extension/src/entrypoints/popup/components/Credentials/Details/LoginCredentialsBlock.tsx
index b855dc25a..c273b4e0a 100644
--- a/apps/browser-extension/src/entrypoints/popup/components/Credentials/Details/LoginCredentialsBlock.tsx
+++ b/apps/browser-extension/src/entrypoints/popup/components/Credentials/Details/LoginCredentialsBlock.tsx
@@ -3,7 +3,7 @@ import { useTranslation } from 'react-i18next';
import { FormInputCopyToClipboard } from '@/entrypoints/popup/components/Forms/FormInputCopyToClipboard';
-import type { Credential } from '@/utils/dist/shared/models/vault';
+import type { Credential } from '@/utils/dist/core/models/vault';
type LoginCredentialsBlockProps = {
credential: Credential;
diff --git a/apps/browser-extension/src/entrypoints/popup/components/Credentials/Details/TotpBlock.tsx b/apps/browser-extension/src/entrypoints/popup/components/Credentials/Details/TotpBlock.tsx
index 4a84122c7..c66739e78 100644
--- a/apps/browser-extension/src/entrypoints/popup/components/Credentials/Details/TotpBlock.tsx
+++ b/apps/browser-extension/src/entrypoints/popup/components/Credentials/Details/TotpBlock.tsx
@@ -5,7 +5,7 @@ import { sendMessage } from 'webext-bridge/popup';
import { useDb } from '@/entrypoints/popup/context/DbContext';
-import type { TotpCode } from '@/utils/dist/shared/models/vault';
+import type { TotpCode } from '@/utils/dist/core/models/vault';
type TotpBlockProps = {
credentialId?: string;
diff --git a/apps/browser-extension/src/entrypoints/popup/components/Credentials/Details/TotpEditor.tsx b/apps/browser-extension/src/entrypoints/popup/components/Credentials/Details/TotpEditor.tsx
index 342e308f7..2c5328807 100644
--- a/apps/browser-extension/src/entrypoints/popup/components/Credentials/Details/TotpEditor.tsx
+++ b/apps/browser-extension/src/entrypoints/popup/components/Credentials/Details/TotpEditor.tsx
@@ -2,7 +2,7 @@ import * as OTPAuth from 'otpauth';
import React, { useState } from 'react';
import { useTranslation } from 'react-i18next';
-import type { TotpCode } from '@/utils/dist/shared/models/vault';
+import type { TotpCode } from '@/utils/dist/core/models/vault';
type TotpFormData = {
name: string;
diff --git a/apps/browser-extension/src/entrypoints/popup/components/Dialogs/PasswordConfigDialog.tsx b/apps/browser-extension/src/entrypoints/popup/components/Dialogs/PasswordConfigDialog.tsx
index 007a3edba..a8c2c2f75 100644
--- a/apps/browser-extension/src/entrypoints/popup/components/Dialogs/PasswordConfigDialog.tsx
+++ b/apps/browser-extension/src/entrypoints/popup/components/Dialogs/PasswordConfigDialog.tsx
@@ -1,8 +1,8 @@
import React, { useState, useEffect, useCallback } from 'react';
import { useTranslation } from 'react-i18next';
-import type { PasswordSettings } from '@/utils/dist/shared/models/vault';
-import { CreatePasswordGenerator } from '@/utils/dist/shared/password-generator';
+import type { PasswordSettings } from '@/utils/dist/core/models/vault';
+import { CreatePasswordGenerator } from '@/utils/dist/core/password-generator';
interface IPasswordConfigDialogProps {
isOpen: boolean;
diff --git a/apps/browser-extension/src/entrypoints/popup/components/EmailPreview.tsx b/apps/browser-extension/src/entrypoints/popup/components/EmailPreview.tsx
index b07b3df6b..746ee5284 100644
--- a/apps/browser-extension/src/entrypoints/popup/components/EmailPreview.tsx
+++ b/apps/browser-extension/src/entrypoints/popup/components/EmailPreview.tsx
@@ -6,7 +6,7 @@ import { useDb } from '@/entrypoints/popup/context/DbContext';
import { useWebApi } from '@/entrypoints/popup/context/WebApiContext';
import { AppInfo } from '@/utils/AppInfo';
-import type { ApiErrorResponse, MailboxEmail } from '@/utils/dist/shared/models/webapi';
+import type { ApiErrorResponse, MailboxEmail } from '@/utils/dist/core/models/webapi';
import { EncryptionUtility } from '@/utils/EncryptionUtility';
import { storage } from '#imports';
diff --git a/apps/browser-extension/src/entrypoints/popup/components/Forms/AddFieldMenu.tsx b/apps/browser-extension/src/entrypoints/popup/components/Forms/AddFieldMenu.tsx
index 01987a085..3b0c8fb5f 100644
--- a/apps/browser-extension/src/entrypoints/popup/components/Forms/AddFieldMenu.tsx
+++ b/apps/browser-extension/src/entrypoints/popup/components/Forms/AddFieldMenu.tsx
@@ -1,7 +1,7 @@
import React, { useState, useCallback, useMemo } from 'react';
import { useTranslation } from 'react-i18next';
-import type { FieldType, ItemType } from '@/utils/dist/shared/models/vault';
+import type { FieldType, ItemType } from '@/utils/dist/core/models/vault';
/**
* Visibility state for optional sections.
diff --git a/apps/browser-extension/src/entrypoints/popup/components/Forms/PasswordField.tsx b/apps/browser-extension/src/entrypoints/popup/components/Forms/PasswordField.tsx
index 7e02f1dda..a1d519792 100644
--- a/apps/browser-extension/src/entrypoints/popup/components/Forms/PasswordField.tsx
+++ b/apps/browser-extension/src/entrypoints/popup/components/Forms/PasswordField.tsx
@@ -4,8 +4,8 @@ import { useTranslation } from 'react-i18next';
import PasswordConfigDialog from '@/entrypoints/popup/components/Dialogs/PasswordConfigDialog';
import { useDb } from '@/entrypoints/popup/context/DbContext';
-import type { PasswordSettings } from '@/utils/dist/shared/models/vault';
-import { CreatePasswordGenerator } from '@/utils/dist/shared/password-generator';
+import type { PasswordSettings } from '@/utils/dist/core/models/vault';
+import { CreatePasswordGenerator } from '@/utils/dist/core/password-generator';
interface IPasswordFieldProps {
id: string;
diff --git a/apps/browser-extension/src/entrypoints/popup/components/Items/ItemCard.tsx b/apps/browser-extension/src/entrypoints/popup/components/Items/ItemCard.tsx
index 15b7fba09..dc72fdde2 100644
--- a/apps/browser-extension/src/entrypoints/popup/components/Items/ItemCard.tsx
+++ b/apps/browser-extension/src/entrypoints/popup/components/Items/ItemCard.tsx
@@ -1,8 +1,8 @@
import React from 'react';
import { useNavigate } from 'react-router-dom';
-import type { Item } from '@/utils/dist/shared/models/vault';
-import { FieldKey } from '@/utils/dist/shared/models/vault';
+import type { Item } from '@/utils/dist/core/models/vault';
+import { FieldKey } from '@/utils/dist/core/models/vault';
import ItemIcon from './ItemIcon';
diff --git a/apps/browser-extension/src/entrypoints/popup/components/Items/ItemIcon.tsx b/apps/browser-extension/src/entrypoints/popup/components/Items/ItemIcon.tsx
index 7f3292207..bb6222df6 100644
--- a/apps/browser-extension/src/entrypoints/popup/components/Items/ItemIcon.tsx
+++ b/apps/browser-extension/src/entrypoints/popup/components/Items/ItemIcon.tsx
@@ -1,7 +1,7 @@
import React from 'react';
-import type { Item } from '@/utils/dist/shared/models/vault';
-import { FieldKey } from '@/utils/dist/shared/models/vault';
+import type { Item } from '@/utils/dist/core/models/vault';
+import { FieldKey } from '@/utils/dist/core/models/vault';
import SqliteClient from '@/utils/SqliteClient';
type ItemIconProps = {
diff --git a/apps/browser-extension/src/entrypoints/popup/components/Items/ItemTypeSelector.tsx b/apps/browser-extension/src/entrypoints/popup/components/Items/ItemTypeSelector.tsx
index 0d355859e..e9d4a277b 100644
--- a/apps/browser-extension/src/entrypoints/popup/components/Items/ItemTypeSelector.tsx
+++ b/apps/browser-extension/src/entrypoints/popup/components/Items/ItemTypeSelector.tsx
@@ -1,7 +1,7 @@
import React from 'react';
import { useTranslation } from 'react-i18next';
-import type { ItemType } from '@/utils/dist/shared/models/vault';
+import type { ItemType } from '@/utils/dist/core/models/vault';
/**
* Item type option configuration.
diff --git a/apps/browser-extension/src/entrypoints/popup/context/DbContext.tsx b/apps/browser-extension/src/entrypoints/popup/context/DbContext.tsx
index 35289df21..cfc021599 100644
--- a/apps/browser-extension/src/entrypoints/popup/context/DbContext.tsx
+++ b/apps/browser-extension/src/entrypoints/popup/context/DbContext.tsx
@@ -1,7 +1,7 @@
import React, { createContext, useContext, useState, useEffect, useCallback, useMemo } from 'react';
import { sendMessage } from 'webext-bridge/popup';
-import type { EncryptionKeyDerivationParams, VaultMetadata } from '@/utils/dist/shared/models/metadata';
+import type { EncryptionKeyDerivationParams, VaultMetadata } from '@/utils/dist/core/models/metadata';
import SqliteClient from '@/utils/SqliteClient';
import type { VaultResponse as messageVaultResponse } from '@/utils/types/messaging/VaultResponse';
diff --git a/apps/browser-extension/src/entrypoints/popup/hooks/useAliasGenerator.ts b/apps/browser-extension/src/entrypoints/popup/hooks/useAliasGenerator.ts
index 6c98c5006..39482ab59 100644
--- a/apps/browser-extension/src/entrypoints/popup/hooks/useAliasGenerator.ts
+++ b/apps/browser-extension/src/entrypoints/popup/hooks/useAliasGenerator.ts
@@ -2,8 +2,8 @@ import { useCallback, useState, type Dispatch, type SetStateAction } from 'react
import { useDb } from '@/entrypoints/popup/context/DbContext';
-import { IdentityHelperUtils, CreateIdentityGenerator, convertAgeRangeToBirthdateOptions } from '@/utils/dist/shared/identity-generator';
-import { CreatePasswordGenerator } from '@/utils/dist/shared/password-generator';
+import { IdentityHelperUtils, CreateIdentityGenerator, convertAgeRangeToBirthdateOptions } from '@/utils/dist/core/identity-generator';
+import { CreatePasswordGenerator } from '@/utils/dist/core/password-generator';
/**
* Generated alias data returned by the hook.
diff --git a/apps/browser-extension/src/entrypoints/popup/hooks/useVaultSync.ts b/apps/browser-extension/src/entrypoints/popup/hooks/useVaultSync.ts
index de7794010..b8f6bec78 100644
--- a/apps/browser-extension/src/entrypoints/popup/hooks/useVaultSync.ts
+++ b/apps/browser-extension/src/entrypoints/popup/hooks/useVaultSync.ts
@@ -6,8 +6,8 @@ import { useApp } from '@/entrypoints/popup/context/AppContext';
import { useDb } from '@/entrypoints/popup/context/DbContext';
import { useWebApi } from '@/entrypoints/popup/context/WebApiContext';
-import type { EncryptionKeyDerivationParams } from '@/utils/dist/shared/models/metadata';
-import type { VaultResponse } from '@/utils/dist/shared/models/webapi';
+import type { EncryptionKeyDerivationParams } from '@/utils/dist/core/models/metadata';
+import type { VaultResponse } from '@/utils/dist/core/models/webapi';
import { EncryptionUtility } from '@/utils/EncryptionUtility';
import { NetworkError } from '@/utils/types/errors/NetworkError';
import { VaultVersionIncompatibleError } from '@/utils/types/errors/VaultVersionIncompatibleError';
diff --git a/apps/browser-extension/src/entrypoints/popup/pages/auth/Login.tsx b/apps/browser-extension/src/entrypoints/popup/pages/auth/Login.tsx
index 690c89fad..40ec2dfeb 100644
--- a/apps/browser-extension/src/entrypoints/popup/pages/auth/Login.tsx
+++ b/apps/browser-extension/src/entrypoints/popup/pages/auth/Login.tsx
@@ -18,7 +18,7 @@ import SrpUtility from '@/entrypoints/popup/utils/SrpUtility';
import { AppInfo } from '@/utils/AppInfo';
import { SrpAuthService } from '@/utils/auth/SrpAuthService';
-import type { VaultResponse, LoginResponse } from '@/utils/dist/shared/models/webapi';
+import type { VaultResponse, LoginResponse } from '@/utils/dist/core/models/webapi';
import { EncryptionUtility } from '@/utils/EncryptionUtility';
import SqliteClient from '@/utils/SqliteClient';
import { ApiAuthError } from '@/utils/types/errors/ApiAuthError';
diff --git a/apps/browser-extension/src/entrypoints/popup/pages/auth/Unlock.tsx b/apps/browser-extension/src/entrypoints/popup/pages/auth/Unlock.tsx
index 6a3407d2e..54aaf0d37 100644
--- a/apps/browser-extension/src/entrypoints/popup/pages/auth/Unlock.tsx
+++ b/apps/browser-extension/src/entrypoints/popup/pages/auth/Unlock.tsx
@@ -20,7 +20,7 @@ import SrpUtility from '@/entrypoints/popup/utils/SrpUtility';
import { SrpAuthService } from '@/utils/auth/SrpAuthService';
import { VAULT_LOCKED_DISMISS_UNTIL_KEY } from '@/utils/Constants';
-import type { EncryptionKeyDerivationParams } from '@/utils/dist/shared/models/metadata';
+import type { EncryptionKeyDerivationParams } from '@/utils/dist/core/models/metadata';
import {
getPinLength,
isPinEnabled,
diff --git a/apps/browser-extension/src/entrypoints/popup/pages/auth/Upgrade.tsx b/apps/browser-extension/src/entrypoints/popup/pages/auth/Upgrade.tsx
index dc0691fd7..3487891d7 100644
--- a/apps/browser-extension/src/entrypoints/popup/pages/auth/Upgrade.tsx
+++ b/apps/browser-extension/src/entrypoints/popup/pages/auth/Upgrade.tsx
@@ -16,8 +16,8 @@ import { useVaultMutate } from '@/entrypoints/popup/hooks/useVaultMutate';
import { useVaultSync } from '@/entrypoints/popup/hooks/useVaultSync';
import { PopoutUtility } from '@/entrypoints/popup/utils/PopoutUtility';
-import type { VaultVersion } from '@/utils/dist/shared/vault-sql';
-import { VaultSqlGenerator } from '@/utils/dist/shared/vault-sql';
+import type { VaultVersion } from '@/utils/dist/core/vault';
+import { VaultSqlGenerator } from '@/utils/dist/core/vault';
/**
* Upgrade page for handling vault version upgrades.
@@ -112,7 +112,7 @@ const Upgrade: React.FC = () => {
setError(null);
try {
- // Get upgrade SQL commands from vault-sql shared library
+ // Get upgrade SQL commands from vault library
const vaultSqlGenerator = new VaultSqlGenerator();
const upgradeResult = vaultSqlGenerator.getUpgradeVaultSql(currentVersion.revision, latestVersion.revision);
diff --git a/apps/browser-extension/src/entrypoints/popup/pages/credentials/CredentialAddEdit.tsx b/apps/browser-extension/src/entrypoints/popup/pages/credentials/CredentialAddEdit.tsx
index 9a671be78..54efb3160 100644
--- a/apps/browser-extension/src/entrypoints/popup/pages/credentials/CredentialAddEdit.tsx
+++ b/apps/browser-extension/src/entrypoints/popup/pages/credentials/CredentialAddEdit.tsx
@@ -25,9 +25,9 @@ import { useWebApi } from '@/entrypoints/popup/context/WebApiContext';
import { useVaultMutate } from '@/entrypoints/popup/hooks/useVaultMutate';
import { SKIP_FORM_RESTORE_KEY } from '@/utils/Constants';
-import { IdentityHelperUtils, CreateIdentityGenerator, CreateUsernameEmailGenerator, Identity, Gender, convertAgeRangeToBirthdateOptions } from '@/utils/dist/shared/identity-generator';
-import type { Attachment, Credential, TotpCode } from '@/utils/dist/shared/models/vault';
-import { CreatePasswordGenerator } from '@/utils/dist/shared/password-generator';
+import { IdentityHelperUtils, CreateIdentityGenerator, CreateUsernameEmailGenerator, Identity, Gender, convertAgeRangeToBirthdateOptions } from '@/utils/dist/core/identity-generator';
+import type { Attachment, Credential, TotpCode } from '@/utils/dist/core/models/vault';
+import { CreatePasswordGenerator } from '@/utils/dist/core/password-generator';
import { ServiceDetectionUtility } from '@/utils/serviceDetection/ServiceDetectionUtility';
import { browser } from '#imports';
diff --git a/apps/browser-extension/src/entrypoints/popup/pages/credentials/CredentialDetails.tsx b/apps/browser-extension/src/entrypoints/popup/pages/credentials/CredentialDetails.tsx
index bc94cc2fa..772b81e65 100644
--- a/apps/browser-extension/src/entrypoints/popup/pages/credentials/CredentialDetails.tsx
+++ b/apps/browser-extension/src/entrypoints/popup/pages/credentials/CredentialDetails.tsx
@@ -18,7 +18,7 @@ import { useHeaderButtons } from '@/entrypoints/popup/context/HeaderButtonsConte
import { useLoading } from '@/entrypoints/popup/context/LoadingContext';
import { PopoutUtility } from '@/entrypoints/popup/utils/PopoutUtility';
-import type { Credential } from '@/utils/dist/shared/models/vault';
+import type { Credential } from '@/utils/dist/core/models/vault';
/**
* Credential details page.
diff --git a/apps/browser-extension/src/entrypoints/popup/pages/credentials/CredentialsList.tsx b/apps/browser-extension/src/entrypoints/popup/pages/credentials/CredentialsList.tsx
index 4d95b625b..30b938075 100644
--- a/apps/browser-extension/src/entrypoints/popup/pages/credentials/CredentialsList.tsx
+++ b/apps/browser-extension/src/entrypoints/popup/pages/credentials/CredentialsList.tsx
@@ -14,7 +14,7 @@ import { useLoading } from '@/entrypoints/popup/context/LoadingContext';
import { useVaultSync } from '@/entrypoints/popup/hooks/useVaultSync';
import { PopoutUtility } from '@/entrypoints/popup/utils/PopoutUtility';
-import type { Credential } from '@/utils/dist/shared/models/vault';
+import type { Credential } from '@/utils/dist/core/models/vault';
import { useMinDurationLoading } from '@/hooks/useMinDurationLoading';
diff --git a/apps/browser-extension/src/entrypoints/popup/pages/credentials/ItemAddEdit.tsx b/apps/browser-extension/src/entrypoints/popup/pages/credentials/ItemAddEdit.tsx
index 791d90e1e..6b7fb99c8 100644
--- a/apps/browser-extension/src/entrypoints/popup/pages/credentials/ItemAddEdit.tsx
+++ b/apps/browser-extension/src/entrypoints/popup/pages/credentials/ItemAddEdit.tsx
@@ -22,8 +22,8 @@ import { useLoading } from '@/entrypoints/popup/context/LoadingContext';
import useAliasGenerator from '@/entrypoints/popup/hooks/useAliasGenerator';
import { useVaultMutate } from '@/entrypoints/popup/hooks/useVaultMutate';
-import type { Item, ItemField, ItemType, FieldType, Attachment, TotpCode } from '@/utils/dist/shared/models/vault';
-import { getSystemFieldsForItemType, isFieldShownByDefault } from '@/utils/dist/shared/models/vault';
+import type { Item, ItemField, ItemType, FieldType, Attachment, TotpCode } from '@/utils/dist/core/models/vault';
+import { getSystemFieldsForItemType, isFieldShownByDefault } from '@/utils/dist/core/models/vault';
// Valid item types from the shared model
const VALID_ITEM_TYPES: ItemType[] = ['Login', 'Alias', 'CreditCard', 'Note'];
diff --git a/apps/browser-extension/src/entrypoints/popup/pages/credentials/ItemDetails.tsx b/apps/browser-extension/src/entrypoints/popup/pages/credentials/ItemDetails.tsx
index a450fc9a7..d5cdae1a1 100644
--- a/apps/browser-extension/src/entrypoints/popup/pages/credentials/ItemDetails.tsx
+++ b/apps/browser-extension/src/entrypoints/popup/pages/credentials/ItemDetails.tsx
@@ -15,8 +15,8 @@ import { useHeaderButtons } from '@/entrypoints/popup/context/HeaderButtonsConte
import { useLoading } from '@/entrypoints/popup/context/LoadingContext';
import { PopoutUtility } from '@/entrypoints/popup/utils/PopoutUtility';
-import type { Item } from '@/utils/dist/shared/models/vault';
-import { groupFieldsByCategory } from '@/utils/dist/shared/models/vault';
+import type { Item } from '@/utils/dist/core/models/vault';
+import { groupFieldsByCategory } from '@/utils/dist/core/models/vault';
/**
* Item details page with dynamic field rendering.
diff --git a/apps/browser-extension/src/entrypoints/popup/pages/credentials/ItemTypeSelector.tsx b/apps/browser-extension/src/entrypoints/popup/pages/credentials/ItemTypeSelector.tsx
index 9a5499730..eb2e32aeb 100644
--- a/apps/browser-extension/src/entrypoints/popup/pages/credentials/ItemTypeSelector.tsx
+++ b/apps/browser-extension/src/entrypoints/popup/pages/credentials/ItemTypeSelector.tsx
@@ -5,7 +5,7 @@ import { useNavigate } from 'react-router-dom';
import { FormInput } from '@/entrypoints/popup/components/Forms/FormInput';
import { useLoading } from '@/entrypoints/popup/context/LoadingContext';
-import type { ItemType } from '@/utils/dist/shared/models/vault';
+import type { ItemType } from '@/utils/dist/core/models/vault';
/**
* Item type option configuration.
diff --git a/apps/browser-extension/src/entrypoints/popup/pages/emails/EmailDetails.tsx b/apps/browser-extension/src/entrypoints/popup/pages/emails/EmailDetails.tsx
index abd0a1719..cc0e0197d 100644
--- a/apps/browser-extension/src/entrypoints/popup/pages/emails/EmailDetails.tsx
+++ b/apps/browser-extension/src/entrypoints/popup/pages/emails/EmailDetails.tsx
@@ -11,7 +11,7 @@ import { useWebApi } from '@/entrypoints/popup/context/WebApiContext';
import ConversionUtility from '@/entrypoints/popup/utils/ConversionUtility';
import { PopoutUtility } from '@/entrypoints/popup/utils/PopoutUtility';
-import type { EmailAttachment, Email } from '@/utils/dist/shared/models/webapi';
+import type { EmailAttachment, Email } from '@/utils/dist/core/models/webapi';
import EncryptionUtility from '@/utils/EncryptionUtility';
import { useMinDurationLoading } from '@/hooks/useMinDurationLoading';
diff --git a/apps/browser-extension/src/entrypoints/popup/pages/emails/EmailsList.tsx b/apps/browser-extension/src/entrypoints/popup/pages/emails/EmailsList.tsx
index 92c91fd91..cb20e2683 100644
--- a/apps/browser-extension/src/entrypoints/popup/pages/emails/EmailsList.tsx
+++ b/apps/browser-extension/src/entrypoints/popup/pages/emails/EmailsList.tsx
@@ -12,7 +12,7 @@ import { useLoading } from '@/entrypoints/popup/context/LoadingContext';
import { useWebApi } from '@/entrypoints/popup/context/WebApiContext';
import { PopoutUtility } from '@/entrypoints/popup/utils/PopoutUtility';
-import type { MailboxBulkRequest, MailboxBulkResponse, MailboxEmail } from '@/utils/dist/shared/models/webapi';
+import type { MailboxBulkRequest, MailboxBulkResponse, MailboxEmail } from '@/utils/dist/core/models/webapi';
import EncryptionUtility from '@/utils/EncryptionUtility';
import { useMinDurationLoading } from '@/hooks/useMinDurationLoading';
diff --git a/apps/browser-extension/src/entrypoints/popup/pages/items/ItemsList.tsx b/apps/browser-extension/src/entrypoints/popup/pages/items/ItemsList.tsx
index 0c2c3888e..3522c702d 100644
--- a/apps/browser-extension/src/entrypoints/popup/pages/items/ItemsList.tsx
+++ b/apps/browser-extension/src/entrypoints/popup/pages/items/ItemsList.tsx
@@ -17,7 +17,7 @@ import { useVaultMutate } from '@/entrypoints/popup/hooks/useVaultMutate';
import { useVaultSync } from '@/entrypoints/popup/hooks/useVaultSync';
import { PopoutUtility } from '@/entrypoints/popup/utils/PopoutUtility';
-import type { Item } from '@/utils/dist/shared/models/vault';
+import type { Item } from '@/utils/dist/core/models/vault';
import { useMinDurationLoading } from '@/hooks/useMinDurationLoading';
diff --git a/apps/browser-extension/src/entrypoints/popup/pages/items/RecentlyDeleted.tsx b/apps/browser-extension/src/entrypoints/popup/pages/items/RecentlyDeleted.tsx
index 2f443624e..407a96f09 100644
--- a/apps/browser-extension/src/entrypoints/popup/pages/items/RecentlyDeleted.tsx
+++ b/apps/browser-extension/src/entrypoints/popup/pages/items/RecentlyDeleted.tsx
@@ -6,7 +6,7 @@ import { useDb } from '@/entrypoints/popup/context/DbContext';
import { useHeaderButtons } from '@/entrypoints/popup/context/HeaderButtonsContext';
import { useVaultMutate } from '@/entrypoints/popup/hooks/useVaultMutate';
-import type { Item } from '@/utils/dist/shared/models/vault';
+import type { Item } from '@/utils/dist/core/models/vault';
import { useMinDurationLoading } from '@/hooks/useMinDurationLoading';
diff --git a/apps/browser-extension/src/entrypoints/popup/pages/passkeys/PasskeyCreate.tsx b/apps/browser-extension/src/entrypoints/popup/pages/passkeys/PasskeyCreate.tsx
index 3d1af529d..5dac1ad5f 100644
--- a/apps/browser-extension/src/entrypoints/popup/pages/passkeys/PasskeyCreate.tsx
+++ b/apps/browser-extension/src/entrypoints/popup/pages/passkeys/PasskeyCreate.tsx
@@ -16,7 +16,7 @@ import { useVaultMutate } from '@/entrypoints/popup/hooks/useVaultMutate';
import { PASSKEY_DISABLED_SITES_KEY } from '@/utils/Constants';
import { extractDomain, extractRootDomain } from '@/utils/credentialMatcher/CredentialMatcher';
-import type { Passkey } from '@/utils/dist/shared/models/vault';
+import type { Passkey } from '@/utils/dist/core/models/vault';
import { PasskeyAuthenticator } from '@/utils/passkey/PasskeyAuthenticator';
import { PasskeyHelper } from '@/utils/passkey/PasskeyHelper';
import type { CreateRequest, PasskeyCreateCredentialResponse, PendingPasskeyCreateRequest } from '@/utils/passkey/types';
diff --git a/apps/browser-extension/src/entrypoints/popup/utils/ConversionUtility.ts b/apps/browser-extension/src/entrypoints/popup/utils/ConversionUtility.ts
index 5caa652a8..ff19763f2 100644
--- a/apps/browser-extension/src/entrypoints/popup/utils/ConversionUtility.ts
+++ b/apps/browser-extension/src/entrypoints/popup/utils/ConversionUtility.ts
@@ -1,6 +1,6 @@
/**
* Utility class for conversion operations.
- * TODO: make this a shared utility class in root /shared/ folder so we can reuse it between browser extension/mobile app
+ * TODO: make this a shared utility class in root /core/ folder so we can reuse it between browser extension/mobile app
* and possibly WASM client.
*/
class ConversionUtility {
diff --git a/apps/browser-extension/src/entrypoints/popup/utils/MobileLoginUtility.ts b/apps/browser-extension/src/entrypoints/popup/utils/MobileLoginUtility.ts
index b5cdaddc7..c48fb66d8 100644
--- a/apps/browser-extension/src/entrypoints/popup/utils/MobileLoginUtility.ts
+++ b/apps/browser-extension/src/entrypoints/popup/utils/MobileLoginUtility.ts
@@ -2,7 +2,7 @@ import { Buffer } from 'buffer';
import { MobileLoginErrorCode } from '@/entrypoints/popup/types/MobileLoginErrorCode';
-import type { LoginResponse, MobileLoginInitiateResponse, MobileLoginPollResponse } from '@/utils/dist/shared/models/webapi';
+import type { LoginResponse, MobileLoginInitiateResponse, MobileLoginPollResponse } from '@/utils/dist/core/models/webapi';
import EncryptionUtility from '@/utils/EncryptionUtility';
import type { MobileLoginResult } from '@/utils/types/messaging/MobileLoginResult';
import type { WebApiService } from '@/utils/WebApiService';
diff --git a/apps/browser-extension/src/entrypoints/popup/utils/SrpUtility.ts b/apps/browser-extension/src/entrypoints/popup/utils/SrpUtility.ts
index 5f1c83834..c492ccda5 100644
--- a/apps/browser-extension/src/entrypoints/popup/utils/SrpUtility.ts
+++ b/apps/browser-extension/src/entrypoints/popup/utils/SrpUtility.ts
@@ -1,5 +1,5 @@
import { SrpAuthService } from '@/utils/auth/SrpAuthService';
-import type { LoginResponse, ValidateLoginResponse, ValidateLoginRequest, ValidateLoginRequest2Fa, BadRequestResponse } from '@/utils/dist/shared/models/webapi';
+import type { LoginResponse, ValidateLoginResponse, ValidateLoginRequest, ValidateLoginRequest2Fa, BadRequestResponse } from '@/utils/dist/core/models/webapi';
import { ApiAuthError } from '@/utils/types/errors/ApiAuthError';
import { WebApiService } from '@/utils/WebApiService';
diff --git a/apps/browser-extension/src/utils/EncryptionUtility.ts b/apps/browser-extension/src/utils/EncryptionUtility.ts
index 30f6dea44..b4a5ed95c 100644
--- a/apps/browser-extension/src/utils/EncryptionUtility.ts
+++ b/apps/browser-extension/src/utils/EncryptionUtility.ts
@@ -2,8 +2,8 @@ import { Buffer } from 'buffer';
import argon2 from 'argon2-browser/dist/argon2-bundled.min.js';
-import type { EncryptionKey } from '@/utils/dist/shared/models/vault';
-import type { Email, MailboxEmail } from '@/utils/dist/shared/models/webapi';
+import type { EncryptionKey } from '@/utils/dist/core/models/vault';
+import type { Email, MailboxEmail } from '@/utils/dist/core/models/webapi';
/**
* Utility class for encryption operations including:
diff --git a/apps/browser-extension/src/utils/SqliteClient.ts b/apps/browser-extension/src/utils/SqliteClient.ts
index 226ca0b6a..2a2d413d0 100644
--- a/apps/browser-extension/src/utils/SqliteClient.ts
+++ b/apps/browser-extension/src/utils/SqliteClient.ts
@@ -1,11 +1,11 @@
import initSqlJs, { Database } from 'sql.js';
import * as dateFormatter from '@/utils/dateFormatter';
-import type { Credential, EncryptionKey, PasswordSettings, TotpCode, Passkey, Item, ItemField, ItemTagRef, FieldType, FieldHistory } from '@/utils/dist/shared/models/vault';
-import type { Attachment } from '@/utils/dist/shared/models/vault';
-import { FieldKey, getSystemField, MAX_FIELD_HISTORY_RECORDS } from '@/utils/dist/shared/models/vault';
-import type { VaultVersion } from '@/utils/dist/shared/vault-sql';
-import { VaultSqlGenerator, checkVersionCompatibility, extractVersionFromMigrationId } from '@/utils/dist/shared/vault-sql';
+import type { Credential, EncryptionKey, PasswordSettings, TotpCode, Passkey, Item, ItemField, ItemTagRef, FieldType, FieldHistory } from '@/utils/dist/core/models/vault';
+import type { Attachment } from '@/utils/dist/core/models/vault';
+import { FieldKey, getSystemField, MAX_FIELD_HISTORY_RECORDS } from '@/utils/dist/core/models/vault';
+import type { VaultVersion } from '@/utils/dist/core/vault';
+import { VaultSqlGenerator, checkVersionCompatibility, extractVersionFromMigrationId } from '@/utils/dist/core/vault';
import { VaultVersionIncompatibleError } from '@/utils/types/errors/VaultVersionIncompatibleError';
import { t } from '@/i18n/StandaloneI18n';
@@ -811,7 +811,7 @@ export class SqliteClient {
}
// Otherwise, try to match UI language to an identity generator language
- const { mapUiLanguageToIdentityLanguage } = await import('@/utils/dist/shared/identity-generator');
+ const { mapUiLanguageToIdentityLanguage } = await import('@/utils/dist/core/identity-generator');
const { default: i18n } = await import('@/i18n/i18n');
const uiLanguage = i18n.language;
diff --git a/apps/browser-extension/src/utils/VaultMergeService.ts b/apps/browser-extension/src/utils/VaultMergeService.ts
index 86386d6e1..5b44db68e 100644
--- a/apps/browser-extension/src/utils/VaultMergeService.ts
+++ b/apps/browser-extension/src/utils/VaultMergeService.ts
@@ -1,7 +1,7 @@
import initSqlJs, { Database, SqlJsStatic, SqlValue } from 'sql.js';
import { browser } from 'wxt/browser';
-import init, { getSyncableTableNames, mergeVaults } from './dist/shared/rust-core/aliasvault_core.js';
+import init, { getSyncableTableNames, mergeVaults } from './dist/core/rust/aliasvault_core.js';
/**
* Record type for JSON data passed to/from Rust.
diff --git a/apps/browser-extension/src/utils/WebApiService.ts b/apps/browser-extension/src/utils/WebApiService.ts
index 1e440734f..ce6ed9f78 100644
--- a/apps/browser-extension/src/utils/WebApiService.ts
+++ b/apps/browser-extension/src/utils/WebApiService.ts
@@ -1,4 +1,4 @@
-import type { StatusResponse } from '@/utils/dist/shared/models/webapi';
+import type { StatusResponse } from '@/utils/dist/core/models/webapi';
import { logoutEventEmitter } from '@/events/LogoutEventEmitter';
diff --git a/apps/browser-extension/src/utils/auth/SrpAuthService.ts b/apps/browser-extension/src/utils/auth/SrpAuthService.ts
index 1a39ffc14..787a2d9b3 100644
--- a/apps/browser-extension/src/utils/auth/SrpAuthService.ts
+++ b/apps/browser-extension/src/utils/auth/SrpAuthService.ts
@@ -1,6 +1,6 @@
import srp from 'secure-remote-password/client';
-import type { TokenModel, LoginResponse, BadRequestResponse } from '@/utils/dist/shared/models/webapi';
+import type { TokenModel, LoginResponse, BadRequestResponse } from '@/utils/dist/core/models/webapi';
import { EncryptionUtility } from '../EncryptionUtility';
diff --git a/apps/browser-extension/src/utils/credentialMatcher/CredentialMatcher.ts b/apps/browser-extension/src/utils/credentialMatcher/CredentialMatcher.ts
index 67a5276c5..f19643d7e 100644
--- a/apps/browser-extension/src/utils/credentialMatcher/CredentialMatcher.ts
+++ b/apps/browser-extension/src/utils/credentialMatcher/CredentialMatcher.ts
@@ -1,4 +1,4 @@
-import type { Credential } from '@/utils/dist/shared/models/vault';
+import type { Credential } from '@/utils/dist/core/models/vault';
import { CombinedStopWords } from '@/utils/formDetector/FieldPatterns';
/**
diff --git a/apps/browser-extension/src/utils/credentialMatcher/__tests__/CredentialMatcher.test.ts b/apps/browser-extension/src/utils/credentialMatcher/__tests__/CredentialMatcher.test.ts
index 7d7d8b5c3..5c47732cf 100644
--- a/apps/browser-extension/src/utils/credentialMatcher/__tests__/CredentialMatcher.test.ts
+++ b/apps/browser-extension/src/utils/credentialMatcher/__tests__/CredentialMatcher.test.ts
@@ -1,7 +1,7 @@
import { describe, it, expect, beforeEach } from 'vitest';
import { filterCredentials } from '@/utils/credentialMatcher/CredentialMatcher';
-import type { Credential } from '@/utils/dist/shared/models/vault';
+import type { Credential } from '@/utils/dist/core/models/vault';
describe('CredentialMatcher - Credential URL Matching', () => {
let testCredentials: Credential[];
diff --git a/apps/browser-extension/src/utils/dist/core/identity-generator/README.md b/apps/browser-extension/src/utils/dist/core/identity-generator/README.md
new file mode 100644
index 000000000..de6a3af68
--- /dev/null
+++ b/apps/browser-extension/src/utils/dist/core/identity-generator/README.md
@@ -0,0 +1,9 @@
+# ⚠️ Auto-Generated Files
+
+This folder contains the output of the core `identity-generator` module from the `/core` directory in the AliasVault project.
+
+**Do not edit any of these files manually.**
+
+To make changes:
+1. Update the source files in the `/core/typescript/identity-generator/src` directory
+2. Run the `build.sh` script in the module directory to regenerate the outputs and copy them here.
diff --git a/apps/browser-extension/src/utils/dist/shared/identity-generator/index.d.ts b/apps/browser-extension/src/utils/dist/core/identity-generator/index.d.ts
similarity index 100%
rename from apps/browser-extension/src/utils/dist/shared/identity-generator/index.d.ts
rename to apps/browser-extension/src/utils/dist/core/identity-generator/index.d.ts
diff --git a/apps/browser-extension/src/utils/dist/shared/identity-generator/index.js b/apps/browser-extension/src/utils/dist/core/identity-generator/index.js
similarity index 100%
rename from apps/browser-extension/src/utils/dist/shared/identity-generator/index.js
rename to apps/browser-extension/src/utils/dist/core/identity-generator/index.js
diff --git a/apps/browser-extension/src/utils/dist/shared/identity-generator/index.mjs b/apps/browser-extension/src/utils/dist/core/identity-generator/index.mjs
similarity index 100%
rename from apps/browser-extension/src/utils/dist/shared/identity-generator/index.mjs
rename to apps/browser-extension/src/utils/dist/core/identity-generator/index.mjs
diff --git a/apps/mobile-app/utils/dist/shared/models/README.md b/apps/browser-extension/src/utils/dist/core/models/README.md
similarity index 51%
rename from apps/mobile-app/utils/dist/shared/models/README.md
rename to apps/browser-extension/src/utils/dist/core/models/README.md
index 57e908a5a..640bafb3b 100644
--- a/apps/mobile-app/utils/dist/shared/models/README.md
+++ b/apps/browser-extension/src/utils/dist/core/models/README.md
@@ -1,9 +1,9 @@
# ⚠️ Auto-Generated Files
-This folder contains the output of the shared `models` module from the `/shared` directory in the AliasVault project.
+This folder contains the output of the core `models` module from the `/core` directory in the AliasVault project.
**Do not edit any of these files manually.**
To make changes:
-1. Update the source files in the `/shared/models/src` directory
+1. Update the source files in the `/core/models/src` directory
2. Run the `build.sh` script in the module directory to regenerate the outputs and copy them here.
diff --git a/apps/browser-extension/src/utils/dist/shared/models/metadata/index.d.ts b/apps/browser-extension/src/utils/dist/core/models/metadata/index.d.ts
similarity index 100%
rename from apps/browser-extension/src/utils/dist/shared/models/metadata/index.d.ts
rename to apps/browser-extension/src/utils/dist/core/models/metadata/index.d.ts
diff --git a/apps/browser-extension/src/utils/dist/shared/models/metadata/index.js b/apps/browser-extension/src/utils/dist/core/models/metadata/index.js
similarity index 100%
rename from apps/browser-extension/src/utils/dist/shared/models/metadata/index.js
rename to apps/browser-extension/src/utils/dist/core/models/metadata/index.js
diff --git a/apps/browser-extension/src/utils/dist/shared/models/vault/index.d.ts b/apps/browser-extension/src/utils/dist/core/models/vault/index.d.ts
similarity index 100%
rename from apps/browser-extension/src/utils/dist/shared/models/vault/index.d.ts
rename to apps/browser-extension/src/utils/dist/core/models/vault/index.d.ts
diff --git a/apps/browser-extension/src/utils/dist/shared/models/vault/index.js b/apps/browser-extension/src/utils/dist/core/models/vault/index.js
similarity index 100%
rename from apps/browser-extension/src/utils/dist/shared/models/vault/index.js
rename to apps/browser-extension/src/utils/dist/core/models/vault/index.js
diff --git a/apps/browser-extension/src/utils/dist/shared/models/webapi/index.d.ts b/apps/browser-extension/src/utils/dist/core/models/webapi/index.d.ts
similarity index 100%
rename from apps/browser-extension/src/utils/dist/shared/models/webapi/index.d.ts
rename to apps/browser-extension/src/utils/dist/core/models/webapi/index.d.ts
diff --git a/apps/browser-extension/src/utils/dist/shared/models/webapi/index.js b/apps/browser-extension/src/utils/dist/core/models/webapi/index.js
similarity index 100%
rename from apps/browser-extension/src/utils/dist/shared/models/webapi/index.js
rename to apps/browser-extension/src/utils/dist/core/models/webapi/index.js
diff --git a/apps/browser-extension/src/utils/dist/core/password-generator/README.md b/apps/browser-extension/src/utils/dist/core/password-generator/README.md
new file mode 100644
index 000000000..ed0527c64
--- /dev/null
+++ b/apps/browser-extension/src/utils/dist/core/password-generator/README.md
@@ -0,0 +1,9 @@
+# ⚠️ Auto-Generated Files
+
+This folder contains the output of the core `password-generator` module from the `/core` directory in the AliasVault project.
+
+**Do not edit any of these files manually.**
+
+To make changes:
+1. Update the source files in the `/core/typescript/password-generator/src` directory
+2. Run the `build.sh` script in the module directory to regenerate the outputs and copy them here.
diff --git a/apps/browser-extension/src/utils/dist/shared/password-generator/index.d.ts b/apps/browser-extension/src/utils/dist/core/password-generator/index.d.ts
similarity index 100%
rename from apps/browser-extension/src/utils/dist/shared/password-generator/index.d.ts
rename to apps/browser-extension/src/utils/dist/core/password-generator/index.d.ts
diff --git a/apps/browser-extension/src/utils/dist/shared/password-generator/index.js b/apps/browser-extension/src/utils/dist/core/password-generator/index.js
similarity index 100%
rename from apps/browser-extension/src/utils/dist/shared/password-generator/index.js
rename to apps/browser-extension/src/utils/dist/core/password-generator/index.js
diff --git a/apps/browser-extension/src/utils/dist/shared/password-generator/index.mjs b/apps/browser-extension/src/utils/dist/core/password-generator/index.mjs
similarity index 100%
rename from apps/browser-extension/src/utils/dist/shared/password-generator/index.mjs
rename to apps/browser-extension/src/utils/dist/core/password-generator/index.mjs
diff --git a/apps/browser-extension/src/utils/dist/shared/models/README.md b/apps/browser-extension/src/utils/dist/core/vault/README.md
similarity index 51%
rename from apps/browser-extension/src/utils/dist/shared/models/README.md
rename to apps/browser-extension/src/utils/dist/core/vault/README.md
index 57e908a5a..b68e8a75e 100644
--- a/apps/browser-extension/src/utils/dist/shared/models/README.md
+++ b/apps/browser-extension/src/utils/dist/core/vault/README.md
@@ -1,9 +1,9 @@
# ⚠️ Auto-Generated Files
-This folder contains the output of the shared `models` module from the `/shared` directory in the AliasVault project.
+This folder contains the output of the core `vault` module from the `/core` directory in the AliasVault project.
**Do not edit any of these files manually.**
To make changes:
-1. Update the source files in the `/shared/models/src` directory
+1. Update the source files in the `/core/vault/src` directory
2. Run the `build.sh` script in the module directory to regenerate the outputs and copy them here.
diff --git a/apps/browser-extension/src/utils/dist/shared/vault-sql/index.d.mts b/apps/browser-extension/src/utils/dist/core/vault/index.d.mts
similarity index 100%
rename from apps/browser-extension/src/utils/dist/shared/vault-sql/index.d.mts
rename to apps/browser-extension/src/utils/dist/core/vault/index.d.mts
diff --git a/apps/browser-extension/src/utils/dist/shared/vault-sql/index.d.ts b/apps/browser-extension/src/utils/dist/core/vault/index.d.ts
similarity index 100%
rename from apps/browser-extension/src/utils/dist/shared/vault-sql/index.d.ts
rename to apps/browser-extension/src/utils/dist/core/vault/index.d.ts
diff --git a/apps/browser-extension/src/utils/dist/shared/vault-sql/index.js b/apps/browser-extension/src/utils/dist/core/vault/index.js
similarity index 100%
rename from apps/browser-extension/src/utils/dist/shared/vault-sql/index.js
rename to apps/browser-extension/src/utils/dist/core/vault/index.js
diff --git a/apps/browser-extension/src/utils/dist/shared/vault-sql/index.mjs b/apps/browser-extension/src/utils/dist/core/vault/index.mjs
similarity index 100%
rename from apps/browser-extension/src/utils/dist/shared/vault-sql/index.mjs
rename to apps/browser-extension/src/utils/dist/core/vault/index.mjs
diff --git a/apps/browser-extension/src/utils/dist/shared/identity-generator/README.md b/apps/browser-extension/src/utils/dist/shared/identity-generator/README.md
deleted file mode 100644
index ccbbee91f..000000000
--- a/apps/browser-extension/src/utils/dist/shared/identity-generator/README.md
+++ /dev/null
@@ -1,9 +0,0 @@
-# ⚠️ Auto-Generated Files
-
-This folder contains the output of the shared `identity-generator` module from the `/shared` directory in the AliasVault project.
-
-**Do not edit any of these files manually.**
-
-To make changes:
-1. Update the source files in the `/shared/identity-generator/src` directory
-2. Run the `build.sh` script in the module directory to regenerate the outputs and copy them here.
diff --git a/apps/browser-extension/src/utils/dist/shared/password-generator/README.md b/apps/browser-extension/src/utils/dist/shared/password-generator/README.md
deleted file mode 100644
index de1a39757..000000000
--- a/apps/browser-extension/src/utils/dist/shared/password-generator/README.md
+++ /dev/null
@@ -1,9 +0,0 @@
-# ⚠️ Auto-Generated Files
-
-This folder contains the output of the shared `password-generator` module from the `/shared` directory in the AliasVault project.
-
-**Do not edit any of these files manually.**
-
-To make changes:
-1. Update the source files in the `/shared/password-generator/src` directory
-2. Run the `build.sh` script in the module directory to regenerate the outputs and copy them here.
diff --git a/apps/browser-extension/src/utils/formDetector/FormFiller.ts b/apps/browser-extension/src/utils/formDetector/FormFiller.ts
index ee44391f2..33988baf8 100644
--- a/apps/browser-extension/src/utils/formDetector/FormFiller.ts
+++ b/apps/browser-extension/src/utils/formDetector/FormFiller.ts
@@ -1,5 +1,5 @@
-import { Gender, IdentityHelperUtils } from "@/utils/dist/shared/identity-generator";
-import type { Credential } from "@/utils/dist/shared/models/vault";
+import { Gender, IdentityHelperUtils } from "@/utils/dist/core/identity-generator";
+import type { Credential } from "@/utils/dist/core/models/vault";
import { CombinedDateOptionPatterns, CombinedGenderOptionPatterns } from "@/utils/formDetector/FieldPatterns";
import { FormFields } from "@/utils/formDetector/types/FormFields";
import { ClickValidator } from "@/utils/security/ClickValidator";
diff --git a/apps/browser-extension/src/utils/formDetector/__tests__/FormFiller.en.test.ts b/apps/browser-extension/src/utils/formDetector/__tests__/FormFiller.en.test.ts
index f248e0155..3612612aa 100644
--- a/apps/browser-extension/src/utils/formDetector/__tests__/FormFiller.en.test.ts
+++ b/apps/browser-extension/src/utils/formDetector/__tests__/FormFiller.en.test.ts
@@ -1,7 +1,7 @@
import { JSDOM } from 'jsdom';
import { describe, it, expect, beforeEach, vi } from 'vitest';
-import type { Credential } from '@/utils/dist/shared/models/vault';
+import type { Credential } from '@/utils/dist/core/models/vault';
import { FormFiller } from '../FormFiller';
import { FormFields } from '../types/FormFields';
diff --git a/apps/browser-extension/src/utils/formDetector/__tests__/FormFiller.generic.test.ts b/apps/browser-extension/src/utils/formDetector/__tests__/FormFiller.generic.test.ts
index 90685f4c3..11fac7877 100644
--- a/apps/browser-extension/src/utils/formDetector/__tests__/FormFiller.generic.test.ts
+++ b/apps/browser-extension/src/utils/formDetector/__tests__/FormFiller.generic.test.ts
@@ -1,7 +1,7 @@
import { JSDOM } from 'jsdom';
import { describe, it, expect, beforeEach, vi } from 'vitest';
-import type { Credential } from '@/utils/dist/shared/models/vault';
+import type { Credential } from '@/utils/dist/core/models/vault';
import { FormFiller } from '../FormFiller';
import { FormFields } from '../types/FormFields';
diff --git a/apps/browser-extension/src/utils/formDetector/__tests__/FormFiller.nl.test.ts b/apps/browser-extension/src/utils/formDetector/__tests__/FormFiller.nl.test.ts
index e97e4459e..83e42f4a0 100644
--- a/apps/browser-extension/src/utils/formDetector/__tests__/FormFiller.nl.test.ts
+++ b/apps/browser-extension/src/utils/formDetector/__tests__/FormFiller.nl.test.ts
@@ -1,7 +1,7 @@
import { JSDOM } from 'jsdom';
import { describe, it, expect, beforeEach, vi } from 'vitest';
-import type { Credential } from '@/utils/dist/shared/models/vault';
+import type { Credential } from '@/utils/dist/core/models/vault';
import { FormFiller } from '../FormFiller';
import { FormFields } from '../types/FormFields';
diff --git a/apps/browser-extension/src/utils/formDetector/__tests__/TestUtils.ts b/apps/browser-extension/src/utils/formDetector/__tests__/TestUtils.ts
index 53688f3e1..ee1c990d8 100644
--- a/apps/browser-extension/src/utils/formDetector/__tests__/TestUtils.ts
+++ b/apps/browser-extension/src/utils/formDetector/__tests__/TestUtils.ts
@@ -4,8 +4,8 @@ import { join } from 'path';
import { JSDOM, DOMWindow } from 'jsdom';
import { it, expect, vi } from 'vitest';
-import { Gender } from '@/utils/dist/shared/identity-generator';
-import type { Credential } from '@/utils/dist/shared/models/vault';
+import { Gender } from '@/utils/dist/core/identity-generator';
+import type { Credential } from '@/utils/dist/core/models/vault';
import { FormDetector } from '@/utils/formDetector/FormDetector';
import { FormFields } from '@/utils/formDetector/types/FormFields';
diff --git a/apps/browser-extension/src/utils/types/messaging/CredentialsResponse.ts b/apps/browser-extension/src/utils/types/messaging/CredentialsResponse.ts
index 5628c8e1b..bf6fd4693 100644
--- a/apps/browser-extension/src/utils/types/messaging/CredentialsResponse.ts
+++ b/apps/browser-extension/src/utils/types/messaging/CredentialsResponse.ts
@@ -1,4 +1,4 @@
-import type { Credential } from "@/utils/dist/shared/models/vault";
+import type { Credential } from "@/utils/dist/core/models/vault";
export type CredentialsResponse = {
success: boolean,
diff --git a/apps/browser-extension/src/utils/types/messaging/PasswordSettingsResponse.ts b/apps/browser-extension/src/utils/types/messaging/PasswordSettingsResponse.ts
index 06427a685..ba8afbe05 100644
--- a/apps/browser-extension/src/utils/types/messaging/PasswordSettingsResponse.ts
+++ b/apps/browser-extension/src/utils/types/messaging/PasswordSettingsResponse.ts
@@ -1,4 +1,4 @@
-import type { PasswordSettings } from "@/utils/dist/shared/models/vault";
+import type { PasswordSettings } from "@/utils/dist/core/models/vault";
export type PasswordSettingsResponse = {
success: boolean,
diff --git a/apps/browser-extension/tests/helpers/test-api.ts b/apps/browser-extension/tests/helpers/test-api.ts
index 658fb223d..487c314fe 100644
--- a/apps/browser-extension/tests/helpers/test-api.ts
+++ b/apps/browser-extension/tests/helpers/test-api.ts
@@ -19,8 +19,8 @@ import argon2 from 'argon2';
import Database from 'better-sqlite3';
import * as srp from 'secure-remote-password/client.js';
-// Get the vault schema SQL from the shared vault-sql package
-import { COMPLETE_SCHEMA_SQL, VAULT_VERSIONS } from '../../src/utils/dist/shared/vault-sql/index.mjs';
+// Get the vault schema SQL from the core vault package
+import { COMPLETE_SCHEMA_SQL, VAULT_VERSIONS } from '../../src/utils/dist/core/vault/index.mjs';
/**
* Token model returned from successful registration/login.
diff --git a/apps/browser-extension/wxt.config.ts b/apps/browser-extension/wxt.config.ts
index 337eb29b8..8086cd797 100644
--- a/apps/browser-extension/wxt.config.ts
+++ b/apps/browser-extension/wxt.config.ts
@@ -63,7 +63,7 @@ export default defineConfig({
dest: 'src'
},
{
- src: 'src/utils/dist/shared/rust-core/aliasvault_core_bg.wasm',
+ src: 'src/utils/dist/core/rust/aliasvault_core_bg.wasm',
dest: 'src'
}
]
diff --git a/apps/mobile-app/app/(tabs)/credentials/[id].tsx b/apps/mobile-app/app/(tabs)/credentials/[id].tsx
index a358c4de1..4247d0de2 100644
--- a/apps/mobile-app/app/(tabs)/credentials/[id].tsx
+++ b/apps/mobile-app/app/(tabs)/credentials/[id].tsx
@@ -4,7 +4,7 @@ import { useCallback, useEffect, useState } from 'react';
import { ActivityIndicator, View, Text, StyleSheet, Linking, Platform } from 'react-native'
import Toast from 'react-native-toast-message';
-import type { Credential } from '@/utils/dist/shared/models/vault';
+import type { Credential } from '@/utils/dist/core/models/vault';
import emitter from '@/utils/EventEmitter';
import { useColors } from '@/hooks/useColorScheme';
diff --git a/apps/mobile-app/app/(tabs)/credentials/add-edit.tsx b/apps/mobile-app/app/(tabs)/credentials/add-edit.tsx
index 132404e0f..548d17ec6 100644
--- a/apps/mobile-app/app/(tabs)/credentials/add-edit.tsx
+++ b/apps/mobile-app/app/(tabs)/credentials/add-edit.tsx
@@ -11,10 +11,10 @@ import { useTranslation } from 'react-i18next';
import { StyleSheet, View, Alert, Keyboard, Platform, ScrollView, KeyboardAvoidingView } from 'react-native';
import Toast from 'react-native-toast-message';
-import { CreateIdentityGenerator, CreateUsernameEmailGenerator, Gender, Identity, IdentityHelperUtils, convertAgeRangeToBirthdateOptions } from '@/utils/dist/shared/identity-generator';
-import type { Attachment, Credential, TotpCode } from '@/utils/dist/shared/models/vault';
-import type { FaviconExtractModel } from '@/utils/dist/shared/models/webapi';
-import { CreatePasswordGenerator, PasswordGenerator } from '@/utils/dist/shared/password-generator';
+import { CreateIdentityGenerator, CreateUsernameEmailGenerator, Gender, Identity, IdentityHelperUtils, convertAgeRangeToBirthdateOptions } from '@/utils/dist/core/identity-generator';
+import type { Attachment, Credential, TotpCode } from '@/utils/dist/core/models/vault';
+import type { FaviconExtractModel } from '@/utils/dist/core/models/webapi';
+import { CreatePasswordGenerator, PasswordGenerator } from '@/utils/dist/core/password-generator';
import emitter from '@/utils/EventEmitter';
import { extractServiceNameFromUrl } from '@/utils/UrlUtility';
import { createCredentialSchema } from '@/utils/ValidationSchema';
diff --git a/apps/mobile-app/app/(tabs)/credentials/index.tsx b/apps/mobile-app/app/(tabs)/credentials/index.tsx
index e8ccc5b57..d1ad8b3b2 100644
--- a/apps/mobile-app/app/(tabs)/credentials/index.tsx
+++ b/apps/mobile-app/app/(tabs)/credentials/index.tsx
@@ -8,7 +8,7 @@ import { StyleSheet, Text, FlatList, TouchableOpacity, TextInput, RefreshControl
import { useSafeAreaInsets } from 'react-native-safe-area-context';
import Toast from 'react-native-toast-message';
-import type { Credential } from '@/utils/dist/shared/models/vault';
+import type { Credential } from '@/utils/dist/core/models/vault';
import emitter from '@/utils/EventEmitter';
import { VaultAuthenticationError } from '@/utils/types/errors/VaultAuthenticationError';
diff --git a/apps/mobile-app/app/(tabs)/emails/[id].tsx b/apps/mobile-app/app/(tabs)/emails/[id].tsx
index 0d7e69bbb..501c8f4d8 100644
--- a/apps/mobile-app/app/(tabs)/emails/[id].tsx
+++ b/apps/mobile-app/app/(tabs)/emails/[id].tsx
@@ -8,8 +8,8 @@ import { useTranslation } from 'react-i18next';
import { StyleSheet, View, ActivityIndicator, Alert, Share, useColorScheme, Linking, Text, TextInput, Platform } from 'react-native';
import { WebView } from 'react-native-webview';
-import type { Credential } from '@/utils/dist/shared/models/vault';
-import type { Email } from '@/utils/dist/shared/models/webapi';
+import type { Credential } from '@/utils/dist/core/models/vault';
+import type { Email } from '@/utils/dist/core/models/webapi';
import EncryptionUtility from '@/utils/EncryptionUtility';
import emitter from '@/utils/EventEmitter';
diff --git a/apps/mobile-app/app/(tabs)/emails/index.tsx b/apps/mobile-app/app/(tabs)/emails/index.tsx
index 33758eed8..cf3288f3b 100644
--- a/apps/mobile-app/app/(tabs)/emails/index.tsx
+++ b/apps/mobile-app/app/(tabs)/emails/index.tsx
@@ -6,7 +6,7 @@ import { StyleSheet, View, ScrollView, RefreshControl, Animated , Platform } fro
import { useSafeAreaInsets } from 'react-native-safe-area-context';
import Toast from 'react-native-toast-message';
-import type { MailboxBulkRequest, MailboxBulkResponse, MailboxEmail } from '@/utils/dist/shared/models/webapi';
+import type { MailboxBulkRequest, MailboxBulkResponse, MailboxEmail } from '@/utils/dist/core/models/webapi';
import EncryptionUtility from '@/utils/EncryptionUtility';
import emitter from '@/utils/EventEmitter';
diff --git a/apps/mobile-app/app/(tabs)/settings/identity-generator.tsx b/apps/mobile-app/app/(tabs)/settings/identity-generator.tsx
index b5c0b899a..b3625aa9e 100644
--- a/apps/mobile-app/app/(tabs)/settings/identity-generator.tsx
+++ b/apps/mobile-app/app/(tabs)/settings/identity-generator.tsx
@@ -4,7 +4,7 @@ import { useState, useCallback, useRef, useEffect } from 'react';
import { useTranslation } from 'react-i18next';
import { StyleSheet, View, Alert, TouchableOpacity } from 'react-native';
-import { getAvailableAgeRanges, IAgeRangeOption, getAvailableLanguages, ILanguageOption } from '@/utils/dist/shared/identity-generator';
+import { getAvailableAgeRanges, IAgeRangeOption, getAvailableLanguages, ILanguageOption } from '@/utils/dist/core/identity-generator';
import { useColors } from '@/hooks/useColorScheme';
import { useVaultMutate } from '@/hooks/useVaultMutate';
diff --git a/apps/mobile-app/app/(tabs)/settings/import-export.tsx b/apps/mobile-app/app/(tabs)/settings/import-export.tsx
index b9673d91e..e79246d86 100644
--- a/apps/mobile-app/app/(tabs)/settings/import-export.tsx
+++ b/apps/mobile-app/app/(tabs)/settings/import-export.tsx
@@ -4,7 +4,7 @@ import * as Sharing from 'expo-sharing';
import { useState } from 'react';
import { StyleSheet, View, TouchableOpacity, Alert } from 'react-native';
-import type { Credential } from '@/utils/dist/shared/models/vault';
+import type { Credential } from '@/utils/dist/core/models/vault';
import { useColors } from '@/hooks/useColorScheme';
import { useTranslation } from '@/hooks/useTranslation';
diff --git a/apps/mobile-app/app/(tabs)/settings/password-generator.tsx b/apps/mobile-app/app/(tabs)/settings/password-generator.tsx
index a4a513036..04dc43948 100644
--- a/apps/mobile-app/app/(tabs)/settings/password-generator.tsx
+++ b/apps/mobile-app/app/(tabs)/settings/password-generator.tsx
@@ -5,8 +5,8 @@ import { useState, useCallback, useRef } from 'react';
import { useTranslation } from 'react-i18next';
import { StyleSheet, View, Alert, TouchableOpacity, Switch, Platform } from 'react-native';
-import type { PasswordSettings } from '@/utils/dist/shared/models/vault';
-import { CreatePasswordGenerator } from '@/utils/dist/shared/password-generator';
+import type { PasswordSettings } from '@/utils/dist/core/models/vault';
+import { CreatePasswordGenerator } from '@/utils/dist/core/password-generator';
import { useColors } from '@/hooks/useColorScheme';
import { useVaultMutate } from '@/hooks/useVaultMutate';
diff --git a/apps/mobile-app/app/(tabs)/settings/security/active-sessions.tsx b/apps/mobile-app/app/(tabs)/settings/security/active-sessions.tsx
index 10f93d320..d4d32af0a 100644
--- a/apps/mobile-app/app/(tabs)/settings/security/active-sessions.tsx
+++ b/apps/mobile-app/app/(tabs)/settings/security/active-sessions.tsx
@@ -4,7 +4,7 @@ import { useTranslation } from 'react-i18next';
import { StyleSheet, View, TouchableOpacity, Alert, RefreshControl, Platform } from 'react-native';
import Toast from 'react-native-toast-message';
-import type { RefreshToken } from '@/utils/dist/shared/models/webapi';
+import type { RefreshToken } from '@/utils/dist/core/models/webapi';
import { useColors } from '@/hooks/useColorScheme';
import { useMinDurationLoading } from '@/hooks/useMinDurationLoading';
diff --git a/apps/mobile-app/app/(tabs)/settings/security/auth-logs.tsx b/apps/mobile-app/app/(tabs)/settings/security/auth-logs.tsx
index 70e68e6ff..87cee8451 100644
--- a/apps/mobile-app/app/(tabs)/settings/security/auth-logs.tsx
+++ b/apps/mobile-app/app/(tabs)/settings/security/auth-logs.tsx
@@ -4,8 +4,8 @@ import { useTranslation } from 'react-i18next';
import { StyleSheet, View, RefreshControl, Platform } from 'react-native';
import Toast from 'react-native-toast-message';
-import type { AuthLogModel } from '@/utils/dist/shared/models/webapi';
-import { AuthEventType } from '@/utils/dist/shared/models/webapi';
+import type { AuthLogModel } from '@/utils/dist/core/models/webapi';
+import { AuthEventType } from '@/utils/dist/core/models/webapi';
import { useColors } from '@/hooks/useColorScheme';
import { useMinDurationLoading } from '@/hooks/useMinDurationLoading';
diff --git a/apps/mobile-app/app/(tabs)/settings/security/delete-account.tsx b/apps/mobile-app/app/(tabs)/settings/security/delete-account.tsx
index 318041cd0..e951767d3 100644
--- a/apps/mobile-app/app/(tabs)/settings/security/delete-account.tsx
+++ b/apps/mobile-app/app/(tabs)/settings/security/delete-account.tsx
@@ -6,7 +6,7 @@ import { useTranslation } from 'react-i18next';
import { StyleSheet, View, Alert, KeyboardAvoidingView, Platform } from 'react-native';
import srp from 'secure-remote-password/client';
-import type { DeleteAccountInitiateRequest, DeleteAccountInitiateResponse, DeleteAccountRequest } from '@/utils/dist/shared/models/webapi';
+import type { DeleteAccountInitiateRequest, DeleteAccountInitiateResponse, DeleteAccountRequest } from '@/utils/dist/core/models/webapi';
import { useColors } from '@/hooks/useColorScheme';
diff --git a/apps/mobile-app/app/login.tsx b/apps/mobile-app/app/login.tsx
index 6eba26797..dcfc0a204 100644
--- a/apps/mobile-app/app/login.tsx
+++ b/apps/mobile-app/app/login.tsx
@@ -9,8 +9,8 @@ import { StyleSheet, View, Text, SafeAreaView, TextInput, ActivityIndicator, Ani
import { useApiUrl } from '@/utils/ApiUrlUtility';
import ConversionUtility from '@/utils/ConversionUtility';
-import type { EncryptionKeyDerivationParams } from '@/utils/dist/shared/models/metadata';
-import type { LoginResponse } from '@/utils/dist/shared/models/webapi';
+import type { EncryptionKeyDerivationParams } from '@/utils/dist/core/models/metadata';
+import type { LoginResponse } from '@/utils/dist/core/models/webapi';
import EncryptionUtility from '@/utils/EncryptionUtility';
import { SrpUtility } from '@/utils/SrpUtility';
import { ApiAuthError } from '@/utils/types/errors/ApiAuthError';
diff --git a/apps/mobile-app/app/upgrade.tsx b/apps/mobile-app/app/upgrade.tsx
index 09ff10771..c32923feb 100644
--- a/apps/mobile-app/app/upgrade.tsx
+++ b/apps/mobile-app/app/upgrade.tsx
@@ -4,8 +4,8 @@ import { useState, useEffect, useCallback } from 'react';
import { useTranslation } from 'react-i18next';
import { StyleSheet, View, Alert, KeyboardAvoidingView, Platform, ScrollView, Dimensions, TouchableWithoutFeedback, Keyboard, Text } from 'react-native';
-import type { VaultVersion } from '@/utils/dist/shared/vault-sql';
-import { VaultSqlGenerator } from '@/utils/dist/shared/vault-sql';
+import type { VaultVersion } from '@/utils/dist/core/vault';
+import { VaultSqlGenerator } from '@/utils/dist/core/vault';
import { useColors } from '@/hooks/useColorScheme';
import { useVaultMutate } from '@/hooks/useVaultMutate';
@@ -134,7 +134,7 @@ export default function UpgradeScreen() : React.ReactNode {
setUpgradeStatus(t('upgrade.status.preparingUpgrade'));
try {
- // Get upgrade SQL commands from vault-sql shared library
+ // Get upgrade SQL commands from vault library
const vaultSqlGenerator = new VaultSqlGenerator();
const upgradeResult = vaultSqlGenerator.getUpgradeVaultSql(currentVersion.revision, latestVersion.revision);
diff --git a/apps/mobile-app/components/EmailCard.tsx b/apps/mobile-app/components/EmailCard.tsx
index 12451aa44..c9cd42529 100644
--- a/apps/mobile-app/components/EmailCard.tsx
+++ b/apps/mobile-app/components/EmailCard.tsx
@@ -2,8 +2,8 @@ import { router } from 'expo-router';
import { useEffect, useState } from 'react';
import { StyleSheet, View } from 'react-native';
-import type { Credential } from '@/utils/dist/shared/models/vault';
-import type { MailboxEmail } from '@/utils/dist/shared/models/webapi';
+import type { Credential } from '@/utils/dist/core/models/vault';
+import type { MailboxEmail } from '@/utils/dist/core/models/webapi';
import { useColors } from '@/hooks/useColorScheme';
import { useTranslation } from '@/hooks/useTranslation';
diff --git a/apps/mobile-app/components/credentials/CredentialCard.tsx b/apps/mobile-app/components/credentials/CredentialCard.tsx
index d28878280..618f033b9 100644
--- a/apps/mobile-app/components/credentials/CredentialCard.tsx
+++ b/apps/mobile-app/components/credentials/CredentialCard.tsx
@@ -6,7 +6,7 @@ import ContextMenu, { OnPressMenuItemEvent } from 'react-native-context-menu-vie
import Toast from 'react-native-toast-message';
import { copyToClipboardWithExpiration } from '@/utils/ClipboardUtility';
-import type { Credential } from '@/utils/dist/shared/models/vault';
+import type { Credential } from '@/utils/dist/core/models/vault';
import { useColors } from '@/hooks/useColorScheme';
diff --git a/apps/mobile-app/components/credentials/details/AliasDetails.tsx b/apps/mobile-app/components/credentials/details/AliasDetails.tsx
index 6768cd932..320ceab84 100644
--- a/apps/mobile-app/components/credentials/details/AliasDetails.tsx
+++ b/apps/mobile-app/components/credentials/details/AliasDetails.tsx
@@ -1,7 +1,7 @@
import { useTranslation } from 'react-i18next';
-import { IdentityHelperUtils } from '@/utils/dist/shared/identity-generator';
-import type { Credential } from '@/utils/dist/shared/models/vault';
+import { IdentityHelperUtils } from '@/utils/dist/core/identity-generator';
+import type { Credential } from '@/utils/dist/core/models/vault';
import FormInputCopyToClipboard from '@/components/form/FormInputCopyToClipboard';
import { ThemedText } from '@/components/themed/ThemedText';
diff --git a/apps/mobile-app/components/credentials/details/AttachmentSection.tsx b/apps/mobile-app/components/credentials/details/AttachmentSection.tsx
index b5aac0bb2..c0e5f7e7e 100644
--- a/apps/mobile-app/components/credentials/details/AttachmentSection.tsx
+++ b/apps/mobile-app/components/credentials/details/AttachmentSection.tsx
@@ -7,7 +7,7 @@ import React, { useState, useEffect, useCallback } from 'react';
import { useTranslation } from 'react-i18next';
import { View, StyleSheet, TouchableOpacity, Alert } from 'react-native';
-import type { Credential, Attachment } from '@/utils/dist/shared/models/vault';
+import type { Credential, Attachment } from '@/utils/dist/core/models/vault';
import emitter from '@/utils/EventEmitter';
import { useColors } from '@/hooks/useColorScheme';
diff --git a/apps/mobile-app/components/credentials/details/AttachmentUploader.tsx b/apps/mobile-app/components/credentials/details/AttachmentUploader.tsx
index 1669c0d0b..52c59757c 100644
--- a/apps/mobile-app/components/credentials/details/AttachmentUploader.tsx
+++ b/apps/mobile-app/components/credentials/details/AttachmentUploader.tsx
@@ -5,7 +5,7 @@ import React, { useState } from 'react';
import { useTranslation } from 'react-i18next';
import { View, StyleSheet, TouchableOpacity, Alert } from 'react-native';
-import type { Attachment } from '@/utils/dist/shared/models/vault';
+import type { Attachment } from '@/utils/dist/core/models/vault';
import { useColors } from '@/hooks/useColorScheme';
diff --git a/apps/mobile-app/components/credentials/details/EmailPreview.tsx b/apps/mobile-app/components/credentials/details/EmailPreview.tsx
index 0441c52fb..eb79573b1 100644
--- a/apps/mobile-app/components/credentials/details/EmailPreview.tsx
+++ b/apps/mobile-app/components/credentials/details/EmailPreview.tsx
@@ -6,7 +6,7 @@ import { useTranslation } from 'react-i18next';
import { View, StyleSheet, TouchableOpacity, Linking, AppState } from 'react-native';
import { AppInfo } from '@/utils/AppInfo';
-import type { ApiErrorResponse, MailboxEmail } from '@/utils/dist/shared/models/webapi';
+import type { ApiErrorResponse, MailboxEmail } from '@/utils/dist/core/models/webapi';
import EncryptionUtility from '@/utils/EncryptionUtility';
import { useColors } from '@/hooks/useColorScheme';
diff --git a/apps/mobile-app/components/credentials/details/LoginCredentials.tsx b/apps/mobile-app/components/credentials/details/LoginCredentials.tsx
index c089f14f3..44f0a5787 100644
--- a/apps/mobile-app/components/credentials/details/LoginCredentials.tsx
+++ b/apps/mobile-app/components/credentials/details/LoginCredentials.tsx
@@ -2,7 +2,7 @@ import MaterialIcons from '@expo/vector-icons/MaterialIcons';
import { useTranslation } from 'react-i18next';
import { StyleSheet, View } from 'react-native';
-import type { Credential } from '@/utils/dist/shared/models/vault';
+import type { Credential } from '@/utils/dist/core/models/vault';
import { useColors } from '@/hooks/useColorScheme';
diff --git a/apps/mobile-app/components/credentials/details/NotesSection.tsx b/apps/mobile-app/components/credentials/details/NotesSection.tsx
index 918de17c9..fd16e30fa 100644
--- a/apps/mobile-app/components/credentials/details/NotesSection.tsx
+++ b/apps/mobile-app/components/credentials/details/NotesSection.tsx
@@ -1,7 +1,7 @@
import { useTranslation } from 'react-i18next';
import { View, Text, StyleSheet, Linking, Pressable } from 'react-native';
-import type { Credential } from '@/utils/dist/shared/models/vault';
+import type { Credential } from '@/utils/dist/core/models/vault';
import { useColors } from '@/hooks/useColorScheme';
diff --git a/apps/mobile-app/components/credentials/details/TotpEditor.tsx b/apps/mobile-app/components/credentials/details/TotpEditor.tsx
index 196ddf7e0..a832541df 100644
--- a/apps/mobile-app/components/credentials/details/TotpEditor.tsx
+++ b/apps/mobile-app/components/credentials/details/TotpEditor.tsx
@@ -4,7 +4,7 @@ import React, { useState } from 'react';
import { useTranslation } from 'react-i18next';
import { View, StyleSheet, Alert, TextInput, Modal, TouchableOpacity, ScrollView } from 'react-native';
-import type { TotpCode } from '@/utils/dist/shared/models/vault';
+import type { TotpCode } from '@/utils/dist/core/models/vault';
import { useColors } from '@/hooks/useColorScheme';
diff --git a/apps/mobile-app/components/credentials/details/TotpSection.tsx b/apps/mobile-app/components/credentials/details/TotpSection.tsx
index 6d2d0d5b1..248ca4da7 100644
--- a/apps/mobile-app/components/credentials/details/TotpSection.tsx
+++ b/apps/mobile-app/components/credentials/details/TotpSection.tsx
@@ -5,7 +5,7 @@ import { View, StyleSheet, TouchableOpacity, Platform } from 'react-native';
import Toast from 'react-native-toast-message';
import { copyToClipboardWithExpiration } from '@/utils/ClipboardUtility';
-import type { Credential, TotpCode } from '@/utils/dist/shared/models/vault';
+import type { Credential, TotpCode } from '@/utils/dist/core/models/vault';
import { useColors } from '@/hooks/useColorScheme';
diff --git a/apps/mobile-app/components/form/AdvancedPasswordField.tsx b/apps/mobile-app/components/form/AdvancedPasswordField.tsx
index 2ca7cf83a..b416726d1 100644
--- a/apps/mobile-app/components/form/AdvancedPasswordField.tsx
+++ b/apps/mobile-app/components/form/AdvancedPasswordField.tsx
@@ -5,8 +5,8 @@ import { Controller, Control, FieldValues, Path } from 'react-hook-form';
import { useTranslation } from 'react-i18next';
import { View, TextInput, TextInputProps, StyleSheet, TouchableOpacity, Platform, Modal, ScrollView, Switch } from 'react-native';
-import type { PasswordSettings } from '@/utils/dist/shared/models/vault';
-import { CreatePasswordGenerator } from '@/utils/dist/shared/password-generator';
+import type { PasswordSettings } from '@/utils/dist/core/models/vault';
+import { CreatePasswordGenerator } from '@/utils/dist/core/password-generator';
import { useColors } from '@/hooks/useColorScheme';
diff --git a/apps/mobile-app/context/DbContext.tsx b/apps/mobile-app/context/DbContext.tsx
index 5b2c2368f..22ea04223 100644
--- a/apps/mobile-app/context/DbContext.tsx
+++ b/apps/mobile-app/context/DbContext.tsx
@@ -1,7 +1,7 @@
import React, { createContext, useContext, useState, useEffect, useCallback, useMemo } from 'react';
-import type { EncryptionKeyDerivationParams, VaultMetadata } from '@/utils/dist/shared/models/metadata';
-import type { VaultResponse } from '@/utils/dist/shared/models/webapi';
+import type { EncryptionKeyDerivationParams, VaultMetadata } from '@/utils/dist/core/models/metadata';
+import type { VaultResponse } from '@/utils/dist/core/models/webapi';
import SqliteClient from '@/utils/SqliteClient';
import NativeVaultManager from '@/specs/NativeVaultManager';
diff --git a/apps/mobile-app/hooks/useVaultMutate.ts b/apps/mobile-app/hooks/useVaultMutate.ts
index 8d72d9354..bf8b90861 100644
--- a/apps/mobile-app/hooks/useVaultMutate.ts
+++ b/apps/mobile-app/hooks/useVaultMutate.ts
@@ -5,8 +5,8 @@ import { useTranslation } from 'react-i18next';
import Toast from 'react-native-toast-message';
import srp from 'secure-remote-password/client';
-import type { EncryptionKeyDerivationParams } from '@/utils/dist/shared/models/metadata';
-import type { PasswordChangeInitiateResponse, Vault, VaultPasswordChangeRequest } from '@/utils/dist/shared/models/webapi';
+import type { EncryptionKeyDerivationParams } from '@/utils/dist/core/models/metadata';
+import type { PasswordChangeInitiateResponse, Vault, VaultPasswordChangeRequest } from '@/utils/dist/core/models/webapi';
import EncryptionUtility from '@/utils/EncryptionUtility';
import { useVaultSync } from '@/hooks/useVaultSync';
diff --git a/apps/mobile-app/hooks/useVaultSync.ts b/apps/mobile-app/hooks/useVaultSync.ts
index e15e4064d..d72042045 100644
--- a/apps/mobile-app/hooks/useVaultSync.ts
+++ b/apps/mobile-app/hooks/useVaultSync.ts
@@ -1,7 +1,7 @@
import { useCallback } from 'react';
import { AppInfo } from '@/utils/AppInfo';
-import type { VaultResponse } from '@/utils/dist/shared/models/webapi';
+import type { VaultResponse } from '@/utils/dist/core/models/webapi';
import { VaultAuthenticationError } from '@/utils/types/errors/VaultAuthenticationError';
import { useTranslation } from '@/hooks/useTranslation';
diff --git a/apps/mobile-app/utils/ConversionUtility.ts b/apps/mobile-app/utils/ConversionUtility.ts
index 7705da603..161a55fd1 100644
--- a/apps/mobile-app/utils/ConversionUtility.ts
+++ b/apps/mobile-app/utils/ConversionUtility.ts
@@ -1,6 +1,6 @@
/**
* Utility class for conversion operations.
- * TODO: make this a shared utility class in root /shared/ folder so we can reuse it between
+ * TODO: make this a shared utility class in root /core/ folder so we can reuse it between
* browser extension/mobile app and possibly WASM client.
*/
class ConversionUtility {
diff --git a/apps/mobile-app/utils/EncryptionUtility.tsx b/apps/mobile-app/utils/EncryptionUtility.tsx
index 1308d27d5..bb7683a40 100644
--- a/apps/mobile-app/utils/EncryptionUtility.tsx
+++ b/apps/mobile-app/utils/EncryptionUtility.tsx
@@ -3,8 +3,8 @@ import { Buffer } from 'buffer';
import AesGcmCrypto from 'react-native-aes-gcm-crypto';
import NativeVaultManager from '@/specs/NativeVaultManager';
-import type { EncryptionKey } from '@/utils/dist/shared/models/vault';
-import type { Email, MailboxEmail } from '@/utils/dist/shared/models/webapi';
+import type { EncryptionKey } from '@/utils/dist/core/models/vault';
+import type { Email, MailboxEmail } from '@/utils/dist/core/models/webapi';
/**
* Utility class for encryption operations including:
diff --git a/apps/mobile-app/utils/SqliteClient.tsx b/apps/mobile-app/utils/SqliteClient.tsx
index ef42df140..53fa9d19d 100644
--- a/apps/mobile-app/utils/SqliteClient.tsx
+++ b/apps/mobile-app/utils/SqliteClient.tsx
@@ -1,8 +1,8 @@
import { Buffer } from 'buffer';
-import type { EncryptionKeyDerivationParams, VaultMetadata } from '@/utils/dist/shared/models/metadata';
-import type { Attachment, Credential, EncryptionKey, PasswordSettings, TotpCode, Passkey } from '@/utils/dist/shared/models/vault';
-import { VaultSqlGenerator, VaultVersion, checkVersionCompatibility, extractVersionFromMigrationId } from '@/utils/dist/shared/vault-sql';
+import type { EncryptionKeyDerivationParams, VaultMetadata } from '@/utils/dist/core/models/metadata';
+import type { Attachment, Credential, EncryptionKey, PasswordSettings, TotpCode, Passkey } from '@/utils/dist/core/models/vault';
+import { VaultSqlGenerator, VaultVersion, checkVersionCompatibility, extractVersionFromMigrationId } from '@/utils/dist/core/vault';
import { VaultVersionIncompatibleError } from '@/utils/types/errors/VaultVersionIncompatibleError';
import NativeVaultManager from '@/specs/NativeVaultManager';
@@ -486,7 +486,7 @@ class SqliteClient {
}
// Otherwise, try to match UI language to an identity generator language
- const { mapUiLanguageToIdentityLanguage } = await import('@/utils/dist/shared/identity-generator');
+ const { mapUiLanguageToIdentityLanguage } = await import('@/utils/dist/core/identity-generator');
const { default: i18n } = await import('@/i18n');
const uiLanguage = i18n.language;
diff --git a/apps/mobile-app/utils/SrpUtility.tsx b/apps/mobile-app/utils/SrpUtility.tsx
index 20df21532..7780e2b49 100644
--- a/apps/mobile-app/utils/SrpUtility.tsx
+++ b/apps/mobile-app/utils/SrpUtility.tsx
@@ -1,6 +1,6 @@
import srp from 'secure-remote-password/client';
-import type { LoginResponse, ValidateLoginRequest2Fa, ValidateLoginResponse, BadRequestResponse } from '@/utils/dist/shared/models/webapi';
+import type { LoginResponse, ValidateLoginRequest2Fa, ValidateLoginResponse, BadRequestResponse } from '@/utils/dist/core/models/webapi';
import { ApiAuthError } from '@/utils/types/errors/ApiAuthError';
import { WebApiService } from '@/utils/WebApiService';
diff --git a/apps/mobile-app/utils/WebApiService.ts b/apps/mobile-app/utils/WebApiService.ts
index 739712cd2..cb3326544 100644
--- a/apps/mobile-app/utils/WebApiService.ts
+++ b/apps/mobile-app/utils/WebApiService.ts
@@ -1,5 +1,5 @@
import { AppInfo } from '@/utils/AppInfo';
-import type { StatusResponse, VaultResponse, AuthLogModel, RefreshToken } from '@/utils/dist/shared/models/webapi';
+import type { StatusResponse, VaultResponse, AuthLogModel, RefreshToken } from '@/utils/dist/core/models/webapi';
import i18n from '@/i18n';
diff --git a/apps/mobile-app/utils/dist/core/identity-generator/README.md b/apps/mobile-app/utils/dist/core/identity-generator/README.md
new file mode 100644
index 000000000..de6a3af68
--- /dev/null
+++ b/apps/mobile-app/utils/dist/core/identity-generator/README.md
@@ -0,0 +1,9 @@
+# ⚠️ Auto-Generated Files
+
+This folder contains the output of the core `identity-generator` module from the `/core` directory in the AliasVault project.
+
+**Do not edit any of these files manually.**
+
+To make changes:
+1. Update the source files in the `/core/typescript/identity-generator/src` directory
+2. Run the `build.sh` script in the module directory to regenerate the outputs and copy them here.
diff --git a/apps/mobile-app/utils/dist/shared/identity-generator/index.d.ts b/apps/mobile-app/utils/dist/core/identity-generator/index.d.ts
similarity index 100%
rename from apps/mobile-app/utils/dist/shared/identity-generator/index.d.ts
rename to apps/mobile-app/utils/dist/core/identity-generator/index.d.ts
diff --git a/apps/mobile-app/utils/dist/shared/identity-generator/index.js b/apps/mobile-app/utils/dist/core/identity-generator/index.js
similarity index 100%
rename from apps/mobile-app/utils/dist/shared/identity-generator/index.js
rename to apps/mobile-app/utils/dist/core/identity-generator/index.js
diff --git a/apps/mobile-app/utils/dist/shared/identity-generator/index.mjs b/apps/mobile-app/utils/dist/core/identity-generator/index.mjs
similarity index 100%
rename from apps/mobile-app/utils/dist/shared/identity-generator/index.mjs
rename to apps/mobile-app/utils/dist/core/identity-generator/index.mjs
diff --git a/apps/mobile-app/utils/dist/shared/vault-sql/README.md b/apps/mobile-app/utils/dist/core/models/README.md
similarity index 50%
rename from apps/mobile-app/utils/dist/shared/vault-sql/README.md
rename to apps/mobile-app/utils/dist/core/models/README.md
index 4db3e7914..640bafb3b 100644
--- a/apps/mobile-app/utils/dist/shared/vault-sql/README.md
+++ b/apps/mobile-app/utils/dist/core/models/README.md
@@ -1,9 +1,9 @@
# ⚠️ Auto-Generated Files
-This folder contains the output of the shared `vault-sql` module from the `/shared` directory in the AliasVault project.
+This folder contains the output of the core `models` module from the `/core` directory in the AliasVault project.
**Do not edit any of these files manually.**
To make changes:
-1. Update the source files in the `/shared/vault-sql/src` directory
+1. Update the source files in the `/core/models/src` directory
2. Run the `build.sh` script in the module directory to regenerate the outputs and copy them here.
diff --git a/apps/mobile-app/utils/dist/shared/models/metadata/index.d.ts b/apps/mobile-app/utils/dist/core/models/metadata/index.d.ts
similarity index 100%
rename from apps/mobile-app/utils/dist/shared/models/metadata/index.d.ts
rename to apps/mobile-app/utils/dist/core/models/metadata/index.d.ts
diff --git a/apps/mobile-app/utils/dist/shared/models/metadata/index.js b/apps/mobile-app/utils/dist/core/models/metadata/index.js
similarity index 100%
rename from apps/mobile-app/utils/dist/shared/models/metadata/index.js
rename to apps/mobile-app/utils/dist/core/models/metadata/index.js
diff --git a/apps/mobile-app/utils/dist/shared/models/vault/index.d.ts b/apps/mobile-app/utils/dist/core/models/vault/index.d.ts
similarity index 100%
rename from apps/mobile-app/utils/dist/shared/models/vault/index.d.ts
rename to apps/mobile-app/utils/dist/core/models/vault/index.d.ts
diff --git a/apps/mobile-app/utils/dist/shared/models/vault/index.js b/apps/mobile-app/utils/dist/core/models/vault/index.js
similarity index 100%
rename from apps/mobile-app/utils/dist/shared/models/vault/index.js
rename to apps/mobile-app/utils/dist/core/models/vault/index.js
diff --git a/apps/mobile-app/utils/dist/shared/models/webapi/index.d.ts b/apps/mobile-app/utils/dist/core/models/webapi/index.d.ts
similarity index 100%
rename from apps/mobile-app/utils/dist/shared/models/webapi/index.d.ts
rename to apps/mobile-app/utils/dist/core/models/webapi/index.d.ts
diff --git a/apps/mobile-app/utils/dist/shared/models/webapi/index.js b/apps/mobile-app/utils/dist/core/models/webapi/index.js
similarity index 100%
rename from apps/mobile-app/utils/dist/shared/models/webapi/index.js
rename to apps/mobile-app/utils/dist/core/models/webapi/index.js
diff --git a/apps/mobile-app/utils/dist/core/password-generator/README.md b/apps/mobile-app/utils/dist/core/password-generator/README.md
new file mode 100644
index 000000000..ed0527c64
--- /dev/null
+++ b/apps/mobile-app/utils/dist/core/password-generator/README.md
@@ -0,0 +1,9 @@
+# ⚠️ Auto-Generated Files
+
+This folder contains the output of the core `password-generator` module from the `/core` directory in the AliasVault project.
+
+**Do not edit any of these files manually.**
+
+To make changes:
+1. Update the source files in the `/core/typescript/password-generator/src` directory
+2. Run the `build.sh` script in the module directory to regenerate the outputs and copy them here.
diff --git a/apps/mobile-app/utils/dist/shared/password-generator/index.d.ts b/apps/mobile-app/utils/dist/core/password-generator/index.d.ts
similarity index 100%
rename from apps/mobile-app/utils/dist/shared/password-generator/index.d.ts
rename to apps/mobile-app/utils/dist/core/password-generator/index.d.ts
diff --git a/apps/mobile-app/utils/dist/shared/password-generator/index.js b/apps/mobile-app/utils/dist/core/password-generator/index.js
similarity index 100%
rename from apps/mobile-app/utils/dist/shared/password-generator/index.js
rename to apps/mobile-app/utils/dist/core/password-generator/index.js
diff --git a/apps/mobile-app/utils/dist/shared/password-generator/index.mjs b/apps/mobile-app/utils/dist/core/password-generator/index.mjs
similarity index 100%
rename from apps/mobile-app/utils/dist/shared/password-generator/index.mjs
rename to apps/mobile-app/utils/dist/core/password-generator/index.mjs
diff --git a/apps/browser-extension/src/utils/dist/shared/vault-sql/README.md b/apps/mobile-app/utils/dist/core/vault/README.md
similarity index 50%
rename from apps/browser-extension/src/utils/dist/shared/vault-sql/README.md
rename to apps/mobile-app/utils/dist/core/vault/README.md
index 4db3e7914..b68e8a75e 100644
--- a/apps/browser-extension/src/utils/dist/shared/vault-sql/README.md
+++ b/apps/mobile-app/utils/dist/core/vault/README.md
@@ -1,9 +1,9 @@
# ⚠️ Auto-Generated Files
-This folder contains the output of the shared `vault-sql` module from the `/shared` directory in the AliasVault project.
+This folder contains the output of the core `vault` module from the `/core` directory in the AliasVault project.
**Do not edit any of these files manually.**
To make changes:
-1. Update the source files in the `/shared/vault-sql/src` directory
+1. Update the source files in the `/core/vault/src` directory
2. Run the `build.sh` script in the module directory to regenerate the outputs and copy them here.
diff --git a/apps/mobile-app/utils/dist/shared/vault-sql/index.d.mts b/apps/mobile-app/utils/dist/core/vault/index.d.mts
similarity index 100%
rename from apps/mobile-app/utils/dist/shared/vault-sql/index.d.mts
rename to apps/mobile-app/utils/dist/core/vault/index.d.mts
diff --git a/apps/mobile-app/utils/dist/shared/vault-sql/index.d.ts b/apps/mobile-app/utils/dist/core/vault/index.d.ts
similarity index 100%
rename from apps/mobile-app/utils/dist/shared/vault-sql/index.d.ts
rename to apps/mobile-app/utils/dist/core/vault/index.d.ts
diff --git a/apps/mobile-app/utils/dist/shared/vault-sql/index.js b/apps/mobile-app/utils/dist/core/vault/index.js
similarity index 100%
rename from apps/mobile-app/utils/dist/shared/vault-sql/index.js
rename to apps/mobile-app/utils/dist/core/vault/index.js
diff --git a/apps/mobile-app/utils/dist/shared/vault-sql/index.mjs b/apps/mobile-app/utils/dist/core/vault/index.mjs
similarity index 100%
rename from apps/mobile-app/utils/dist/shared/vault-sql/index.mjs
rename to apps/mobile-app/utils/dist/core/vault/index.mjs
diff --git a/apps/mobile-app/utils/dist/shared/identity-generator/README.md b/apps/mobile-app/utils/dist/shared/identity-generator/README.md
deleted file mode 100644
index ccbbee91f..000000000
--- a/apps/mobile-app/utils/dist/shared/identity-generator/README.md
+++ /dev/null
@@ -1,9 +0,0 @@
-# ⚠️ Auto-Generated Files
-
-This folder contains the output of the shared `identity-generator` module from the `/shared` directory in the AliasVault project.
-
-**Do not edit any of these files manually.**
-
-To make changes:
-1. Update the source files in the `/shared/identity-generator/src` directory
-2. Run the `build.sh` script in the module directory to regenerate the outputs and copy them here.
diff --git a/apps/mobile-app/utils/dist/shared/password-generator/README.md b/apps/mobile-app/utils/dist/shared/password-generator/README.md
deleted file mode 100644
index de1a39757..000000000
--- a/apps/mobile-app/utils/dist/shared/password-generator/README.md
+++ /dev/null
@@ -1,9 +0,0 @@
-# ⚠️ Auto-Generated Files
-
-This folder contains the output of the shared `password-generator` module from the `/shared` directory in the AliasVault project.
-
-**Do not edit any of these files manually.**
-
-To make changes:
-1. Update the source files in the `/shared/password-generator/src` directory
-2. Run the `build.sh` script in the module directory to regenerate the outputs and copy them here.
diff --git a/apps/server/AliasVault.Client/Services/JsInterop/JsInteropService.cs b/apps/server/AliasVault.Client/Services/JsInterop/JsInteropService.cs
index 4fcbf54eb..88d8ee603 100644
--- a/apps/server/AliasVault.Client/Services/JsInterop/JsInteropService.cs
+++ b/apps/server/AliasVault.Client/Services/JsInterop/JsInteropService.cs
@@ -34,19 +34,19 @@ public sealed class JsInteropService(IJSRuntime jsRuntime)
/// A task representing the asynchronous operation.
public async Task InitializeAsync()
{
- _identityGeneratorModule = await jsRuntime.InvokeAsync("import", $"./js/dist/shared/identity-generator/index.mjs?v={_cacheBuster}");
+ _identityGeneratorModule = await jsRuntime.InvokeAsync("import", $"./js/dist/core/identity-generator/index.mjs?v={_cacheBuster}");
if (_identityGeneratorModule == null)
{
throw new InvalidOperationException("Failed to initialize identity generator module");
}
- _passwordGeneratorModule = await jsRuntime.InvokeAsync("import", $"./js/dist/shared/password-generator/index.mjs?v={_cacheBuster}");
+ _passwordGeneratorModule = await jsRuntime.InvokeAsync("import", $"./js/dist/core/password-generator/index.mjs?v={_cacheBuster}");
if (_passwordGeneratorModule == null)
{
throw new InvalidOperationException("Failed to initialize password generator module");
}
- _vaultSqlInteropModule = await jsRuntime.InvokeAsync("import", $"./js/dist/shared/vault-sql/index.mjs?v={_cacheBuster}");
+ _vaultSqlInteropModule = await jsRuntime.InvokeAsync("import", $"./js/dist/core/vault/index.mjs?v={_cacheBuster}");
if (_vaultSqlInteropModule == null)
{
throw new InvalidOperationException("Failed to initialize vault SQL generator module");
diff --git a/apps/server/AliasVault.Client/wwwroot/js/dist/core/identity-generator/README.md b/apps/server/AliasVault.Client/wwwroot/js/dist/core/identity-generator/README.md
new file mode 100644
index 000000000..de6a3af68
--- /dev/null
+++ b/apps/server/AliasVault.Client/wwwroot/js/dist/core/identity-generator/README.md
@@ -0,0 +1,9 @@
+# ⚠️ Auto-Generated Files
+
+This folder contains the output of the core `identity-generator` module from the `/core` directory in the AliasVault project.
+
+**Do not edit any of these files manually.**
+
+To make changes:
+1. Update the source files in the `/core/typescript/identity-generator/src` directory
+2. Run the `build.sh` script in the module directory to regenerate the outputs and copy them here.
diff --git a/apps/server/AliasVault.Client/wwwroot/js/dist/shared/identity-generator/index.d.ts b/apps/server/AliasVault.Client/wwwroot/js/dist/core/identity-generator/index.d.ts
similarity index 100%
rename from apps/server/AliasVault.Client/wwwroot/js/dist/shared/identity-generator/index.d.ts
rename to apps/server/AliasVault.Client/wwwroot/js/dist/core/identity-generator/index.d.ts
diff --git a/apps/server/AliasVault.Client/wwwroot/js/dist/shared/identity-generator/index.js b/apps/server/AliasVault.Client/wwwroot/js/dist/core/identity-generator/index.js
similarity index 100%
rename from apps/server/AliasVault.Client/wwwroot/js/dist/shared/identity-generator/index.js
rename to apps/server/AliasVault.Client/wwwroot/js/dist/core/identity-generator/index.js
diff --git a/apps/server/AliasVault.Client/wwwroot/js/dist/shared/identity-generator/index.mjs b/apps/server/AliasVault.Client/wwwroot/js/dist/core/identity-generator/index.mjs
similarity index 100%
rename from apps/server/AliasVault.Client/wwwroot/js/dist/shared/identity-generator/index.mjs
rename to apps/server/AliasVault.Client/wwwroot/js/dist/core/identity-generator/index.mjs
diff --git a/apps/server/AliasVault.Client/wwwroot/js/dist/core/password-generator/README.md b/apps/server/AliasVault.Client/wwwroot/js/dist/core/password-generator/README.md
new file mode 100644
index 000000000..ed0527c64
--- /dev/null
+++ b/apps/server/AliasVault.Client/wwwroot/js/dist/core/password-generator/README.md
@@ -0,0 +1,9 @@
+# ⚠️ Auto-Generated Files
+
+This folder contains the output of the core `password-generator` module from the `/core` directory in the AliasVault project.
+
+**Do not edit any of these files manually.**
+
+To make changes:
+1. Update the source files in the `/core/typescript/password-generator/src` directory
+2. Run the `build.sh` script in the module directory to regenerate the outputs and copy them here.
diff --git a/apps/server/AliasVault.Client/wwwroot/js/dist/shared/password-generator/index.d.ts b/apps/server/AliasVault.Client/wwwroot/js/dist/core/password-generator/index.d.ts
similarity index 100%
rename from apps/server/AliasVault.Client/wwwroot/js/dist/shared/password-generator/index.d.ts
rename to apps/server/AliasVault.Client/wwwroot/js/dist/core/password-generator/index.d.ts
diff --git a/apps/server/AliasVault.Client/wwwroot/js/dist/shared/password-generator/index.js b/apps/server/AliasVault.Client/wwwroot/js/dist/core/password-generator/index.js
similarity index 100%
rename from apps/server/AliasVault.Client/wwwroot/js/dist/shared/password-generator/index.js
rename to apps/server/AliasVault.Client/wwwroot/js/dist/core/password-generator/index.js
diff --git a/apps/server/AliasVault.Client/wwwroot/js/dist/shared/password-generator/index.mjs b/apps/server/AliasVault.Client/wwwroot/js/dist/core/password-generator/index.mjs
similarity index 100%
rename from apps/server/AliasVault.Client/wwwroot/js/dist/shared/password-generator/index.mjs
rename to apps/server/AliasVault.Client/wwwroot/js/dist/core/password-generator/index.mjs
diff --git a/apps/server/AliasVault.Client/wwwroot/js/dist/core/vault/README.md b/apps/server/AliasVault.Client/wwwroot/js/dist/core/vault/README.md
new file mode 100644
index 000000000..b68e8a75e
--- /dev/null
+++ b/apps/server/AliasVault.Client/wwwroot/js/dist/core/vault/README.md
@@ -0,0 +1,9 @@
+# ⚠️ Auto-Generated Files
+
+This folder contains the output of the core `vault` module from the `/core` directory in the AliasVault project.
+
+**Do not edit any of these files manually.**
+
+To make changes:
+1. Update the source files in the `/core/vault/src` directory
+2. Run the `build.sh` script in the module directory to regenerate the outputs and copy them here.
diff --git a/apps/server/AliasVault.Client/wwwroot/js/dist/shared/vault-sql/index.d.mts b/apps/server/AliasVault.Client/wwwroot/js/dist/core/vault/index.d.mts
similarity index 100%
rename from apps/server/AliasVault.Client/wwwroot/js/dist/shared/vault-sql/index.d.mts
rename to apps/server/AliasVault.Client/wwwroot/js/dist/core/vault/index.d.mts
diff --git a/apps/server/AliasVault.Client/wwwroot/js/dist/shared/vault-sql/index.d.ts b/apps/server/AliasVault.Client/wwwroot/js/dist/core/vault/index.d.ts
similarity index 100%
rename from apps/server/AliasVault.Client/wwwroot/js/dist/shared/vault-sql/index.d.ts
rename to apps/server/AliasVault.Client/wwwroot/js/dist/core/vault/index.d.ts
diff --git a/apps/server/AliasVault.Client/wwwroot/js/dist/shared/vault-sql/index.js b/apps/server/AliasVault.Client/wwwroot/js/dist/core/vault/index.js
similarity index 100%
rename from apps/server/AliasVault.Client/wwwroot/js/dist/shared/vault-sql/index.js
rename to apps/server/AliasVault.Client/wwwroot/js/dist/core/vault/index.js
diff --git a/apps/server/AliasVault.Client/wwwroot/js/dist/shared/vault-sql/index.mjs b/apps/server/AliasVault.Client/wwwroot/js/dist/core/vault/index.mjs
similarity index 100%
rename from apps/server/AliasVault.Client/wwwroot/js/dist/shared/vault-sql/index.mjs
rename to apps/server/AliasVault.Client/wwwroot/js/dist/core/vault/index.mjs
diff --git a/apps/server/AliasVault.Client/wwwroot/js/dist/shared/identity-generator/README.md b/apps/server/AliasVault.Client/wwwroot/js/dist/shared/identity-generator/README.md
deleted file mode 100644
index ccbbee91f..000000000
--- a/apps/server/AliasVault.Client/wwwroot/js/dist/shared/identity-generator/README.md
+++ /dev/null
@@ -1,9 +0,0 @@
-# ⚠️ Auto-Generated Files
-
-This folder contains the output of the shared `identity-generator` module from the `/shared` directory in the AliasVault project.
-
-**Do not edit any of these files manually.**
-
-To make changes:
-1. Update the source files in the `/shared/identity-generator/src` directory
-2. Run the `build.sh` script in the module directory to regenerate the outputs and copy them here.
diff --git a/apps/server/AliasVault.Client/wwwroot/js/dist/shared/password-generator/README.md b/apps/server/AliasVault.Client/wwwroot/js/dist/shared/password-generator/README.md
deleted file mode 100644
index de1a39757..000000000
--- a/apps/server/AliasVault.Client/wwwroot/js/dist/shared/password-generator/README.md
+++ /dev/null
@@ -1,9 +0,0 @@
-# ⚠️ Auto-Generated Files
-
-This folder contains the output of the shared `password-generator` module from the `/shared` directory in the AliasVault project.
-
-**Do not edit any of these files manually.**
-
-To make changes:
-1. Update the source files in the `/shared/password-generator/src` directory
-2. Run the `build.sh` script in the module directory to regenerate the outputs and copy them here.
diff --git a/apps/server/AliasVault.Client/wwwroot/js/dist/shared/vault-sql/README.md b/apps/server/AliasVault.Client/wwwroot/js/dist/shared/vault-sql/README.md
deleted file mode 100644
index 4db3e7914..000000000
--- a/apps/server/AliasVault.Client/wwwroot/js/dist/shared/vault-sql/README.md
+++ /dev/null
@@ -1,9 +0,0 @@
-# ⚠️ Auto-Generated Files
-
-This folder contains the output of the shared `vault-sql` module from the `/shared` directory in the AliasVault project.
-
-**Do not edit any of these files manually.**
-
-To make changes:
-1. Update the source files in the `/shared/vault-sql/src` directory
-2. Run the `build.sh` script in the module directory to regenerate the outputs and copy them here.
diff --git a/apps/server/Databases/AliasClientDb/Scripts/README.md b/apps/server/Databases/AliasClientDb/Scripts/README.md
index bf70d0276..b88f4de63 100644
--- a/apps/server/Databases/AliasClientDb/Scripts/README.md
+++ b/apps/server/Databases/AliasClientDb/Scripts/README.md
@@ -1,7 +1,7 @@
# SQL Generation Scripts
-This directory contains scripts to generate SQL files from Entity Framework Core migrations and convert them to TypeScript constants which are used by the `./shared/vault-sql` shared TS library.
+This directory contains scripts to generate SQL files from Entity Framework Core migrations and convert them to TypeScript constants which are used by the `./core/vault` TypeScript library.
-This shared TS library is consumed by the web app, browser extensions and mobile apps for vault creation and upgrades.
+This library is consumed by the web app, browser extensions and mobile apps for vault creation and upgrades.
Refer to the docs `upgrade-ef-client-model.md` for how this scripts are used.
\ No newline at end of file
diff --git a/apps/server/Databases/AliasClientDb/Scripts/convert-sql-to-ts.sh b/apps/server/Databases/AliasClientDb/Scripts/convert-sql-to-ts.sh
index 7da0e547a..ebf66acaa 100755
--- a/apps/server/Databases/AliasClientDb/Scripts/convert-sql-to-ts.sh
+++ b/apps/server/Databases/AliasClientDb/Scripts/convert-sql-to-ts.sh
@@ -8,8 +8,8 @@ SQL_DIR="MigrationSql"
OUTPUT_FILE="MigrationTs/SqlConstants.ts"
TEMP_DIR="/tmp/sql_to_ts"
-# Path to the shared vault-sql package
-SHARED_SQL_DIR="../../../../../shared/vault-sql/src/sql"
+# Path to the core vault package
+SHARED_SQL_DIR="../../../../../core/vault/src/sql"
# Create temp directory and output directory
mkdir -p "$TEMP_DIR"
@@ -56,7 +56,7 @@ extract_version_info() {
echo "$version|$readable_desc|$release_date"
}
-# Function to copy files to shared vault-sql directory
+# Function to copy files to core vault directory
copy_to_shared_sql() {
local source_file="$1"
local target_file="$2"
@@ -65,9 +65,9 @@ copy_to_shared_sql() {
echo "Copying $source_file to $target_file"
cp "$source_file" "$target_file"
if [ $? -eq 0 ]; then
- echo "✓ Successfully copied to shared vault-sql directory"
+ echo "✓ Successfully copied to core vault directory"
else
- echo "✗ Failed to copy to shared vault-sql directory"
+ echo "✗ Failed to copy to core vault directory"
return 1
fi
else
@@ -151,13 +151,13 @@ echo "TypeScript constants file generated: $OUTPUT_FILE"
echo "Total migrations processed: ${#migration_files[@]}"
-# Copy generated files to shared vault-sql directory
+# Copy generated files to core vault directory
echo ""
-echo "Copying generated files to shared vault-sql directory..."
+echo "Copying generated files to core vault directory..."
-# Check if shared directory exists
+# Check if core vault directory exists
if [ ! -d "$SHARED_SQL_DIR" ]; then
- echo "✗ Shared vault-sql directory not found: $SHARED_SQL_DIR"
+ echo "✗ Core vault directory not found: $SHARED_SQL_DIR"
echo "Make sure you're running this script from the correct location"
exit 1
fi
diff --git a/apps/server/Databases/AliasClientDb/Scripts/run-all.sh b/apps/server/Databases/AliasClientDb/Scripts/run-all.sh
index 10f9cd7c6..713d04a1d 100755
--- a/apps/server/Databases/AliasClientDb/Scripts/run-all.sh
+++ b/apps/server/Databases/AliasClientDb/Scripts/run-all.sh
@@ -41,9 +41,9 @@ echo "Generated files:"
echo "- SQL files: MigrationSql/"
echo "- TypeScript files: MigrationTs/"
echo ""
-echo "The TypeScript files have been copied to the shared vault-sql directory."
+echo "The TypeScript files have been copied to the core vault directory."
echo ""
-echo "Next, make sure to add the new vault SQL migrations to the VaultVersions.ts file in the vault-sql library."
+echo "Next, make sure to add the new vault SQL migrations to the VaultVersions.ts file in the vault library."
echo ""
-echo "Afterwards, run the following command to build and distribute the vault-sql library:"
-echo "shared/build-and-distribute.sh"
\ No newline at end of file
+echo "Afterwards, run the following command to build and distribute the vault library:"
+echo "core/build-and-distribute.sh"
\ No newline at end of file
diff --git a/shared/.gitignore b/core/.gitignore
similarity index 100%
rename from shared/.gitignore
rename to core/.gitignore
diff --git a/core/README.md b/core/README.md
new file mode 100644
index 000000000..0bf78c8c5
--- /dev/null
+++ b/core/README.md
@@ -0,0 +1,48 @@
+# Core Libraries
+
+This folder contains core modules that are used by multiple applications in the AliasVault monorepo.
+
+## rust (Primary)
+
+**Primary cross-platform core library** written in Rust, providing shared business logic across ALL platforms:
+- Browser extensions (Chrome, Firefox, Edge, Safari) via WebAssembly
+- Mobile apps (iOS via Swift bindings, Android via Kotlin bindings)
+- Server (.NET via P/Invoke)
+- Desktop apps (future)
+
+Currently implements:
+- **merge** - Merges two SQLite vault databases using Last-Write-Wins (LWW) strategy
+- **credential_matcher** - Cross-platform credential filtering for autofill
+
+See [rust/README.md](rust/README.md) for detailed documentation.
+
+## models
+
+TypeScript models that are auto-generated to platform-specific code:
+- TypeScript (source of truth)
+- C# (.NET)
+- Swift (iOS)
+- Kotlin (Android)
+
+## vault
+
+Vault database schema and SQL utilities for:
+- Browser extension
+- Mobile apps (React Native)
+- Web client (Blazor)
+
+## typescript/ (Legacy)
+
+Legacy TypeScript implementations that may be migrated to Rust in the future:
+
+### typescript/identity-generator
+
+TypeScript identity generator used by:
+- Browser extension (React and custom TypeScript)
+- Mobile apps (React Native)
+
+### typescript/password-generator
+
+TypeScript password generator used by:
+- Browser extension (React and custom TypeScript)
+- Mobile apps (React Native)
diff --git a/core/build-and-distribute.sh b/core/build-and-distribute.sh
new file mode 100755
index 000000000..4a7a19fda
--- /dev/null
+++ b/core/build-and-distribute.sh
@@ -0,0 +1,41 @@
+#!/bin/bash
+
+set -e # Stop on error
+set -u # Treat unset variables as errors
+
+# Make all build scripts executable
+chmod +x ./typescript/identity-generator/build.sh
+chmod +x ./typescript/password-generator/build.sh
+chmod +x ./models/build.sh
+chmod +x ./vault/build.sh
+chmod +x ./rust/build.sh
+
+# Run all build scripts
+echo "🚀 Starting build process for all modules..."
+
+# TypeScript packages (legacy - to be migrated to Rust)
+cd ./typescript/identity-generator
+./build.sh
+
+cd ../password-generator
+./build.sh
+
+# Models (TypeScript source of truth -> generates C#, Swift, Kotlin)
+cd ../../models
+./build.sh
+
+# Vault database schema & SQL utilities
+cd ../vault
+./build.sh
+
+# Rust core build (optional - requires Rust toolchain)
+cd ../rust
+if command -v rustc &> /dev/null; then
+ echo "📦 Building rust core (Rust toolchain detected)..."
+ ./build.sh --browser
+else
+ echo "⚠️ Skipping rust core build (Rust not installed)"
+ echo " Install Rust from https://rustup.rs to enable Rust core builds"
+fi
+
+echo "✅ All builds completed successfully."
diff --git a/shared/models/README.md b/core/models/README.md
similarity index 90%
rename from shared/models/README.md
rename to core/models/README.md
index 2ec1616c1..324d6413a 100644
--- a/shared/models/README.md
+++ b/core/models/README.md
@@ -1,4 +1,4 @@
-# Shared Models
+# Core Models
This package serves as the **single source of truth** for data models across all AliasVault platforms.
@@ -8,8 +8,8 @@ This package performs two key functions:
### 1. TypeScript Distribution (As-Is)
Builds and copies TypeScript models directly to:
-- **Browser Extension**: `apps/browser-extension/src/utils/dist/shared/models`
-- **Mobile App**: `apps/mobile-app/utils/dist/shared/models`
+- **Browser Extension**: `apps/browser-extension/src/utils/dist/core/models`
+- **Mobile App**: `apps/mobile-app/utils/dist/core/models`
These apps consume the TypeScript models as-is, enabling type-safe development with no manual synchronization needed.
diff --git a/shared/models/build.sh b/core/models/build.sh
similarity index 75%
rename from shared/models/build.sh
rename to core/models/build.sh
index 3200450d3..a1b414031 100755
--- a/shared/models/build.sh
+++ b/core/models/build.sh
@@ -5,8 +5,8 @@ set -u # Treat unset variables as errors
# Define output targets for models
TARGETS=(
- "../../apps/browser-extension/src/utils/dist/shared/models"
- "../../apps/mobile-app/utils/dist/shared/models"
+ "../../apps/browser-extension/src/utils/dist/core/models"
+ "../../apps/mobile-app/utils/dist/core/models"
)
# Build and distribute models
@@ -41,12 +41,12 @@ for target in "${TARGETS[@]}"; do
cat > "$target/README.md" < {
initialized = true;
}
+// ═══════════════════════════════════════════════════════════════════════════════
+// Merge Functions
+// ═══════════════════════════════════════════════════════════════════════════════
+
/**
* Get the list of table names that need to be synced.
*/
@@ -222,19 +263,49 @@ export function merge(input: MergeInput): MergeOutput {
return mergeVaults(input) as MergeOutput;
}
-export { init, getSyncableTableNames, mergeVaults };
+// ═══════════════════════════════════════════════════════════════════════════════
+// Credential Matcher Functions
+// ═══════════════════════════════════════════════════════════════════════════════
+
+/**
+ * Filter credentials for autofill based on current URL and page context.
+ *
+ * @param credentials - List of credentials to filter
+ * @param currentUrl - Current page URL or app package name
+ * @param pageTitle - Current page title (optional)
+ * @param matchingMode - Matching mode (default, url_exact, url_subdomain)
+ * @returns Filtered credentials (max 3)
+ */
+export function filterCredentials(
+ credentials: CredentialForMatching[],
+ currentUrl: string,
+ pageTitle: string = '',
+ matchingMode: AutofillMatchingMode = 'default'
+): CredentialForMatching[] {
+ if (!initialized) throw new Error('Call initRustCore() first');
+ const input: CredentialMatcherInput = {
+ credentials,
+ current_url: currentUrl,
+ page_title: pageTitle,
+ matching_mode: matchingMode,
+ };
+ const output = wasmFilterCredentials(input) as CredentialMatcherOutput;
+ return output.credentials;
+}
+
+export { init, getSyncableTableNames, mergeVaults, wasmFilterCredentials };
TYPESCRIPT_EOF
# Create README
cat > "$BROWSER_EXT_DIST/README.md" << 'README_EOF'
# Rust Core WASM Module
-Auto-generated from `/shared/rust-core`. Do not edit manually.
+Auto-generated from `/core/rust`. Do not edit manually.
## Usage
```typescript
-import { initRustCore, merge, getTableNames } from './rust-core';
+import { initRustCore, merge, getTableNames } from './rust';
// Initialize once at startup
await initRustCore();
@@ -269,7 +340,7 @@ for (const table of result.tables) {
## Regenerate
```bash
-cd /shared/rust-core
+cd /core/rust
./build.sh --browser
```
README_EOF
diff --git a/core/rust/src/credential_matcher/domain.rs b/core/rust/src/credential_matcher/domain.rs
new file mode 100644
index 000000000..d0de91df0
--- /dev/null
+++ b/core/rust/src/credential_matcher/domain.rs
@@ -0,0 +1,274 @@
+//! Domain extraction and matching utilities.
+
+use std::collections::HashSet;
+
+/// Common top-level domains (TLDs) used for app package name detection.
+/// When a search string starts with one of these TLDs followed by a dot (e.g., "com.coolblue.app"),
+/// it's identified as a reversed domain name (app package name) rather than a regular URL.
+static COMMON_TLDS: &[&str] = &[
+ // Generic TLDs
+ "com", "net", "org", "edu", "gov", "mil", "int",
+ // Country code TLDs
+ "nl", "de", "uk", "fr", "it", "es", "pl", "be", "ch", "at", "se", "no", "dk", "fi",
+ "pt", "gr", "cz", "hu", "ro", "bg", "hr", "sk", "si", "lt", "lv", "ee", "ie", "lu",
+ "us", "ca", "mx", "br", "ar", "cl", "co", "ve", "pe", "ec",
+ "au", "nz", "jp", "cn", "in", "kr", "tw", "hk", "sg", "my", "th", "id", "ph", "vn",
+ "za", "eg", "ng", "ke", "ug", "tz", "ma",
+ "ru", "ua", "by", "kz", "il", "tr", "sa", "ae", "qa", "kw",
+ // New gTLDs (common ones)
+ "app", "dev", "io", "ai", "tech", "shop", "store", "online", "site", "website",
+ "blog", "news", "media", "tv", "video", "music", "pro", "info", "biz", "name",
+];
+
+/// Common two-level public TLDs for root domain extraction.
+static TWO_LEVEL_TLDS: &[&str] = &[
+ // Australia
+ "com.au", "net.au", "org.au", "edu.au", "gov.au", "asn.au", "id.au",
+ // United Kingdom
+ "co.uk", "org.uk", "net.uk", "ac.uk", "gov.uk", "plc.uk", "ltd.uk", "me.uk",
+ // Canada
+ "co.ca", "net.ca", "org.ca", "gc.ca", "ab.ca", "bc.ca", "mb.ca", "nb.ca", "nf.ca", "nl.ca", "ns.ca", "nt.ca", "nu.ca",
+ "on.ca", "pe.ca", "qc.ca", "sk.ca", "yk.ca",
+ // India
+ "co.in", "net.in", "org.in", "edu.in", "gov.in", "ac.in", "res.in", "gen.in", "firm.in", "ind.in",
+ // Japan
+ "co.jp", "ne.jp", "or.jp", "ac.jp", "ad.jp", "ed.jp", "go.jp", "gr.jp", "lg.jp",
+ // South Africa
+ "co.za", "net.za", "org.za", "edu.za", "gov.za", "ac.za", "web.za",
+ // New Zealand
+ "co.nz", "net.nz", "org.nz", "edu.nz", "govt.nz", "ac.nz", "geek.nz", "gen.nz", "kiwi.nz", "maori.nz", "mil.nz", "school.nz",
+ // Brazil
+ "com.br", "net.br", "org.br", "edu.br", "gov.br", "mil.br", "art.br", "etc.br", "adv.br", "arq.br", "bio.br", "cim.br",
+ "cng.br", "cnt.br", "ecn.br", "eng.br", "esp.br", "eti.br", "far.br", "fnd.br", "fot.br", "fst.br", "g12.br", "geo.br",
+ "ggf.br", "jor.br", "lel.br", "mat.br", "med.br", "mus.br", "not.br", "ntr.br", "odo.br", "ppg.br", "pro.br", "psc.br",
+ "psi.br", "qsl.br", "rec.br", "slg.br", "srv.br", "tmp.br", "trd.br", "tur.br", "tv.br", "vet.br", "zlg.br",
+ // Russia
+ "com.ru", "net.ru", "org.ru", "edu.ru", "gov.ru", "int.ru", "mil.ru", "spb.ru", "msk.ru",
+ // China
+ "com.cn", "net.cn", "org.cn", "edu.cn", "gov.cn", "mil.cn", "ac.cn", "ah.cn", "bj.cn", "cq.cn", "fj.cn", "gd.cn", "gs.cn",
+ "gz.cn", "gx.cn", "ha.cn", "hb.cn", "he.cn", "hi.cn", "hk.cn", "hl.cn", "hn.cn", "jl.cn", "js.cn", "jx.cn", "ln.cn", "mo.cn",
+ "nm.cn", "nx.cn", "qh.cn", "sc.cn", "sd.cn", "sh.cn", "sn.cn", "sx.cn", "tj.cn", "tw.cn", "xj.cn", "xz.cn", "yn.cn", "zj.cn",
+ // Mexico
+ "com.mx", "net.mx", "org.mx", "edu.mx", "gob.mx",
+ // Argentina
+ "com.ar", "net.ar", "org.ar", "edu.ar", "gov.ar", "mil.ar", "int.ar",
+ // Chile
+ "com.cl", "net.cl", "org.cl", "edu.cl", "gov.cl", "mil.cl",
+ // Colombia
+ "com.co", "net.co", "org.co", "edu.co", "gov.co", "mil.co", "nom.co",
+ // Venezuela
+ "com.ve", "net.ve", "org.ve", "edu.ve", "gov.ve", "mil.ve", "web.ve",
+ // Peru
+ "com.pe", "net.pe", "org.pe", "edu.pe", "gob.pe", "mil.pe", "nom.pe",
+ // Ecuador
+ "com.ec", "net.ec", "org.ec", "edu.ec", "gov.ec", "mil.ec", "med.ec", "fin.ec", "pro.ec", "info.ec",
+ // Europe
+ "co.at", "or.at", "ac.at", "gv.at", "priv.at",
+ "co.be", "ac.be",
+ "co.dk", "ac.dk",
+ "co.il", "net.il", "org.il", "ac.il", "gov.il", "idf.il", "k12.il", "muni.il",
+ "co.no", "ac.no", "priv.no",
+ "co.pl", "net.pl", "org.pl", "edu.pl", "gov.pl", "mil.pl", "nom.pl", "com.pl",
+ "co.th", "net.th", "org.th", "edu.th", "gov.th", "mil.th", "ac.th", "in.th",
+ "co.kr", "net.kr", "org.kr", "edu.kr", "gov.kr", "mil.kr", "ac.kr", "go.kr", "ne.kr", "or.kr", "pe.kr", "re.kr", "seoul.kr",
+ "kyonggi.kr",
+ // Others
+ "co.id", "net.id", "org.id", "edu.id", "gov.id", "mil.id", "web.id", "ac.id", "sch.id",
+ "co.ma", "net.ma", "org.ma", "edu.ma", "gov.ma", "ac.ma", "press.ma",
+ "co.ke", "net.ke", "org.ke", "edu.ke", "gov.ke", "ac.ke", "go.ke", "info.ke", "me.ke", "mobi.ke", "sc.ke",
+ "co.ug", "net.ug", "org.ug", "edu.ug", "gov.ug", "ac.ug", "sc.ug", "go.ug", "ne.ug", "or.ug",
+ "co.tz", "net.tz", "org.tz", "edu.tz", "gov.tz", "ac.tz", "go.tz", "hotel.tz", "info.tz", "me.tz", "mil.tz", "mobi.tz",
+ "ne.tz", "or.tz", "sc.tz", "tv.tz",
+];
+
+/// Check if a string is likely an app package name (reversed domain).
+/// Package names start with TLD followed by dot (e.g., "com.example", "nl.app").
+pub fn is_app_package_name(text: &str) -> bool {
+ // Must contain a dot
+ if !text.contains('.') {
+ return false;
+ }
+
+ // Must not have protocol
+ if text.starts_with("http://") || text.starts_with("https://") {
+ return false;
+ }
+
+ // Extract first part before first dot
+ let first_part = text.split('.').next().unwrap_or("").to_lowercase();
+
+ // Check if first part is a common TLD - indicates reversed domain (package name)
+ let tld_set: HashSet<&str> = COMMON_TLDS.iter().copied().collect();
+ tld_set.contains(first_part.as_str())
+}
+
+/// Extract domain from URL, handling both full URLs and partial domains.
+/// Returns empty string if not a valid URL/domain.
+pub fn extract_domain(url: &str) -> String {
+ if url.is_empty() {
+ return String::new();
+ }
+
+ let mut domain = url.to_lowercase();
+
+ // Check if it has a protocol
+ let has_protocol = domain.starts_with("http://") || domain.starts_with("https://");
+
+ // If no protocol and starts with TLD + dot, it's likely an app package name
+ if !has_protocol && is_app_package_name(&domain) {
+ return String::new();
+ }
+
+ // Remove protocol if present
+ if let Some(stripped) = domain.strip_prefix("https://") {
+ domain = stripped.to_string();
+ } else if let Some(stripped) = domain.strip_prefix("http://") {
+ domain = stripped.to_string();
+ }
+
+ // Remove www. prefix
+ if let Some(stripped) = domain.strip_prefix("www.") {
+ domain = stripped.to_string();
+ }
+
+ // Remove path, query, and fragment
+ if let Some(pos) = domain.find('/') {
+ domain = domain[..pos].to_string();
+ }
+ if let Some(pos) = domain.find('?') {
+ domain = domain[..pos].to_string();
+ }
+ if let Some(pos) = domain.find('#') {
+ domain = domain[..pos].to_string();
+ }
+
+ // Basic domain validation - must contain at least one dot and valid characters
+ if !domain.contains('.') {
+ return String::new();
+ }
+
+ // Check for valid domain characters
+ if !domain.chars().all(|c| c.is_ascii_alphanumeric() || c == '.' || c == '-') {
+ return String::new();
+ }
+
+ // Ensure valid domain structure
+ if domain.starts_with('.') || domain.ends_with('.') || domain.contains("..") {
+ return String::new();
+ }
+
+ domain
+}
+
+/// Extract root domain from a domain string.
+/// E.g., "sub.example.com" -> "example.com"
+/// E.g., "sub.example.com.au" -> "example.com.au"
+/// E.g., "sub.example.co.uk" -> "example.co.uk"
+pub fn extract_root_domain(domain: &str) -> String {
+ let parts: Vec<&str> = domain.split('.').collect();
+ if parts.len() < 2 {
+ return domain.to_string();
+ }
+
+ let two_level_set: HashSet<&str> = TWO_LEVEL_TLDS.iter().copied().collect();
+
+ // Check if the last two parts form a known two-level TLD
+ if parts.len() >= 3 {
+ let last_two_parts = format!("{}.{}", parts[parts.len() - 2], parts[parts.len() - 1]);
+ if two_level_set.contains(last_two_parts.as_str()) {
+ // Take the last three parts for two-level TLDs
+ return parts[parts.len() - 3..].join(".");
+ }
+ }
+
+ // Default to last two parts for regular TLDs
+ if parts.len() >= 2 {
+ parts[parts.len() - 2..].join(".")
+ } else {
+ domain.to_string()
+ }
+}
+
+/// Check if two domains match, supporting partial matches.
+/// Note: Both parameters should be pre-extracted domains (without protocol, www, path, etc.)
+pub fn domains_match(domain1: &str, domain2: &str) -> bool {
+ if domain1.is_empty() || domain2.is_empty() {
+ return false;
+ }
+
+ // Exact match
+ if domain1 == domain2 {
+ return true;
+ }
+
+ // Check if one domain contains the other (for subdomain matching)
+ if domain1.contains(domain2) || domain2.contains(domain1) {
+ return true;
+ }
+
+ // Check root domain match
+ let d1_root = extract_root_domain(domain1);
+ let d2_root = extract_root_domain(domain2);
+
+ d1_root == d2_root
+}
+
+#[cfg(test)]
+mod tests {
+ use super::*;
+
+ #[test]
+ fn test_is_app_package_name() {
+ assert!(is_app_package_name("com.coolblue.app"));
+ assert!(is_app_package_name("nl.marktplaats.android"));
+ assert!(is_app_package_name("org.example.app"));
+
+ assert!(!is_app_package_name("https://example.com"));
+ assert!(!is_app_package_name("example.com"));
+ assert!(!is_app_package_name("coolblue.nl"));
+ assert!(!is_app_package_name("nodot"));
+ }
+
+ #[test]
+ fn test_extract_domain() {
+ assert_eq!(extract_domain("https://www.example.com/path"), "example.com");
+ assert_eq!(extract_domain("http://example.com"), "example.com");
+ assert_eq!(extract_domain("example.com"), "example.com");
+ assert_eq!(extract_domain("www.example.com"), "example.com");
+ assert_eq!(extract_domain("https://example.com?query=1"), "example.com");
+ assert_eq!(extract_domain("https://example.com#fragment"), "example.com");
+
+ // Package names should return empty
+ assert_eq!(extract_domain("com.coolblue.app"), "");
+
+ // Invalid domains
+ assert_eq!(extract_domain(""), "");
+ assert_eq!(extract_domain("nodot"), "");
+ }
+
+ #[test]
+ fn test_extract_root_domain() {
+ assert_eq!(extract_root_domain("sub.example.com"), "example.com");
+ assert_eq!(extract_root_domain("example.com"), "example.com");
+ assert_eq!(extract_root_domain("sub.example.co.uk"), "example.co.uk");
+ assert_eq!(extract_root_domain("example.co.uk"), "example.co.uk");
+ assert_eq!(extract_root_domain("sub.example.com.au"), "example.com.au");
+ }
+
+ #[test]
+ fn test_domains_match() {
+ // Exact match
+ assert!(domains_match("example.com", "example.com"));
+
+ // Subdomain match
+ assert!(domains_match("sub.example.com", "example.com"));
+ assert!(domains_match("example.com", "sub.example.com"));
+
+ // Root domain match
+ assert!(domains_match("app.example.com", "www.example.com"));
+
+ // No match
+ assert!(!domains_match("example.com", "different.com"));
+ assert!(!domains_match("coolblue.nl", "coolblue.be"));
+ }
+}
diff --git a/core/rust/src/credential_matcher/mod.rs b/core/rust/src/credential_matcher/mod.rs
new file mode 100644
index 000000000..b6e145ed6
--- /dev/null
+++ b/core/rust/src/credential_matcher/mod.rs
@@ -0,0 +1,313 @@
+//! Credential filtering for autofill across all platforms.
+//!
+//! This implementation follows the unified filtering algorithm specification
+//! for cross-platform consistency with browser extensions, iOS, and Android.
+//!
+//! Algorithm Structure (Priority Order with Early Returns):
+//! 1. PRIORITY 1: App Package Name Exact Match (for mobile apps)
+//! 2. PRIORITY 2: URL Domain Matching (exact, subdomain, root domain)
+//! 3. PRIORITY 3: Service Name Fallback (only for credentials without URLs - anti-phishing)
+//! 4. PRIORITY 4: Text/Page Title Matching (non-URL search)
+
+mod domain;
+mod stop_words;
+
+use serde::{Deserialize, Serialize};
+use std::collections::HashSet;
+
+pub use domain::{extract_domain, extract_root_domain};
+use domain::{domains_match, is_app_package_name};
+use stop_words::STOP_WORDS;
+
+/// Matching mode for credential filtering.
+#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
+#[serde(rename_all = "snake_case")]
+pub enum AutofillMatchingMode {
+ #[default]
+ Default,
+ UrlExact,
+ UrlSubdomain,
+}
+
+/// A credential record for matching.
+#[derive(Debug, Clone, Serialize, Deserialize)]
+#[serde(rename_all = "PascalCase")]
+pub struct Credential {
+ pub id: String,
+ pub service_name: Option,
+ pub service_url: Option,
+ #[serde(default)]
+ pub username: Option,
+}
+
+/// Input for credential filtering.
+#[derive(Debug, Clone, Serialize, Deserialize)]
+pub struct CredentialMatcherInput {
+ /// List of credentials to filter
+ pub credentials: Vec,
+ /// Current URL or app package name
+ pub current_url: String,
+ /// Current page title (optional)
+ #[serde(default)]
+ pub page_title: String,
+ /// Matching mode
+ #[serde(default)]
+ pub matching_mode: AutofillMatchingMode,
+}
+
+/// Output from credential filtering.
+#[derive(Debug, Clone, Serialize, Deserialize)]
+pub struct CredentialMatcherOutput {
+ /// Filtered credentials (max 3)
+ pub credentials: Vec,
+ /// Which priority level matched (1-4, or 0 if no match)
+ pub matched_priority: u8,
+}
+
+/// Internal credential with priority for sorting.
+#[derive(Debug, Clone)]
+struct CredentialWithPriority {
+ credential: Credential,
+ priority: u8,
+}
+
+/// Filter credentials based on current URL and page context with anti-phishing protection.
+///
+/// # Arguments
+/// * `input` - CredentialMatcherInput containing credentials and search context
+///
+/// # Returns
+/// CredentialMatcherOutput with filtered credentials (max 3)
+pub fn filter_credentials(input: CredentialMatcherInput) -> CredentialMatcherOutput {
+ let CredentialMatcherInput {
+ credentials,
+ current_url,
+ page_title,
+ matching_mode,
+ } = input;
+
+ // Early return for empty URL
+ if current_url.is_empty() {
+ return CredentialMatcherOutput {
+ credentials: vec![],
+ matched_priority: 0,
+ };
+ }
+
+ // ═══════════════════════════════════════════════════════════════════════════════
+ // PRIORITY 1: App Package Name Exact Match
+ // Check if current URL is an app package name (e.g., com.coolblue.app)
+ // ═══════════════════════════════════════════════════════════════════════════════
+ let is_package_name = is_app_package_name(¤t_url);
+ if is_package_name {
+ let package_matches: Vec = credentials
+ .iter()
+ .filter(|cred| {
+ cred.service_url
+ .as_ref()
+ .map(|url| !url.is_empty() && url == ¤t_url)
+ .unwrap_or(false)
+ })
+ .cloned()
+ .collect();
+
+ // EARLY RETURN if matches found
+ if !package_matches.is_empty() {
+ return CredentialMatcherOutput {
+ credentials: package_matches.into_iter().take(3).collect(),
+ matched_priority: 1,
+ };
+ }
+ // If no matches found, skip URL matching and go directly to text matching (Priority 4)
+ }
+
+ // ═══════════════════════════════════════════════════════════════════════════════
+ // PRIORITY 2: URL Domain Matching
+ // Try to extract domain from current URL (skip if package name)
+ // ═══════════════════════════════════════════════════════════════════════════════
+ if !is_package_name {
+ let current_domain = extract_domain(¤t_url);
+
+ if !current_domain.is_empty() {
+ let mut filtered: Vec = Vec::new();
+
+ // Determine matching features based on mode
+ let enable_exact_match = true; // Always enabled
+ let enable_subdomain_match = matches!(
+ matching_mode,
+ AutofillMatchingMode::Default | AutofillMatchingMode::UrlSubdomain
+ );
+
+ // Process credentials with service URLs
+ for cred in &credentials {
+ let service_url = match &cred.service_url {
+ Some(url) if !url.is_empty() => url,
+ _ => continue, // Handle these in Priority 3
+ };
+
+ let cred_domain = extract_domain(service_url);
+ if cred_domain.is_empty() {
+ continue;
+ }
+
+ // Check for exact match (priority 1)
+ if enable_exact_match && current_domain == cred_domain {
+ filtered.push(CredentialWithPriority {
+ credential: cred.clone(),
+ priority: 1,
+ });
+ continue;
+ }
+
+ // Check for subdomain/partial match (priority 2)
+ if enable_subdomain_match && domains_match(¤t_domain, &cred_domain) {
+ filtered.push(CredentialWithPriority {
+ credential: cred.clone(),
+ priority: 2,
+ });
+ }
+ }
+
+ // EARLY RETURN if matches found
+ if !filtered.is_empty() {
+ // Sort by priority, deduplicate by ID, take first 3
+ filtered.sort_by_key(|c| c.priority);
+ let mut seen_ids: HashSet = HashSet::new();
+ let unique_credentials: Vec = filtered
+ .into_iter()
+ .filter(|c| seen_ids.insert(c.credential.id.clone()))
+ .map(|c| c.credential)
+ .take(3)
+ .collect();
+
+ return CredentialMatcherOutput {
+ credentials: unique_credentials,
+ matched_priority: 2,
+ };
+ }
+
+ // ═══════════════════════════════════════════════════════════════════════════
+ // PRIORITY 3: Page Title / Service Name Fallback (Anti-Phishing Protection)
+ // No domain matches found - search in service names using page title
+ // CRITICAL: Only search credentials with NO service URL defined
+ // ═══════════════════════════════════════════════════════════════════════════
+ if !page_title.is_empty() {
+ let title_words = extract_words(&page_title);
+
+ if !title_words.is_empty() {
+ let name_matches: Vec = credentials
+ .iter()
+ .filter(|cred| {
+ // SECURITY: Skip credentials that have a URL defined
+ if cred.service_url.as_ref().map(|u| !u.is_empty()).unwrap_or(false) {
+ return false;
+ }
+
+ // Check page title match with service name
+ if let Some(service_name) = &cred.service_name {
+ let cred_name_words = extract_words(service_name);
+
+ // Match only complete words, not substrings
+ title_words.iter().any(|title_word| {
+ cred_name_words.iter().any(|cred_word| title_word == cred_word)
+ })
+ } else {
+ false
+ }
+ })
+ .cloned()
+ .collect();
+
+ // Return matches from Priority 3 if any found
+ if !name_matches.is_empty() {
+ return CredentialMatcherOutput {
+ credentials: name_matches.into_iter().take(3).collect(),
+ matched_priority: 3,
+ };
+ }
+ }
+ }
+
+ // No matches found in Priority 2 or Priority 3
+ return CredentialMatcherOutput {
+ credentials: vec![],
+ matched_priority: 0,
+ };
+ }
+ }
+
+ // ═══════════════════════════════════════════════════════════════════════════════
+ // PRIORITY 4: Text Matching
+ // Used when: 1) Package name didn't match in Priority 1, OR 2) URL extraction failed
+ // Performs word-based matching on service names
+ // ═══════════════════════════════════════════════════════════════════════════════
+ let search_words = extract_words(¤t_url);
+
+ if !search_words.is_empty() {
+ let text_matches: Vec = credentials
+ .iter()
+ .filter(|cred| {
+ if let Some(service_name) = &cred.service_name {
+ let service_name_words = extract_words(service_name);
+
+ // Check if any search word matches any service name word exactly
+ search_words
+ .iter()
+ .any(|search_word| service_name_words.contains(search_word))
+ } else {
+ false
+ }
+ })
+ .cloned()
+ .collect();
+
+ if !text_matches.is_empty() {
+ return CredentialMatcherOutput {
+ credentials: text_matches.into_iter().take(3).collect(),
+ matched_priority: 4,
+ };
+ }
+ }
+
+ // No matches found
+ CredentialMatcherOutput {
+ credentials: vec![],
+ matched_priority: 0,
+ }
+}
+
+/// Extract meaningful words from text, removing punctuation and filtering stop words.
+fn extract_words(text: &str) -> Vec {
+ if text.is_empty() {
+ return vec![];
+ }
+
+ let stop_words: HashSet<&str> = STOP_WORDS.iter().copied().collect();
+
+ text.to_lowercase()
+ // Replace common separators and punctuation with spaces (including dots)
+ .chars()
+ .map(|c| {
+ if c.is_alphanumeric() || c == ' ' {
+ c
+ } else {
+ ' '
+ }
+ })
+ .collect::()
+ .split_whitespace()
+ .filter(|word| word.len() > 3 && !stop_words.contains(*word))
+ .map(String::from)
+ .collect()
+}
+
+/// Filter credentials from JSON input (convenience function for FFI).
+pub fn filter_credentials_json(input_json: &str) -> Result {
+ let input: CredentialMatcherInput =
+ serde_json::from_str(input_json).map_err(|e| e.to_string())?;
+ let output = filter_credentials(input);
+ serde_json::to_string(&output).map_err(|e| e.to_string())
+}
+
+#[cfg(test)]
+mod tests;
diff --git a/core/rust/src/credential_matcher/stop_words.rs b/core/rust/src/credential_matcher/stop_words.rs
new file mode 100644
index 000000000..7d75067c6
--- /dev/null
+++ b/core/rust/src/credential_matcher/stop_words.rs
@@ -0,0 +1,79 @@
+//! Stop words for filtering page titles during credential matching.
+//!
+//! These words are filtered out to prevent generic terms from causing false positives.
+
+/// Combined stop words from all supported languages (English + Dutch).
+pub static STOP_WORDS: &[&str] = &[
+ // ═══════════════════════════════════════════════════════════════════════════════
+ // English Stop Words
+ // ═══════════════════════════════════════════════════════════════════════════════
+
+ // Authentication related
+ "login", "signin", "sign", "register", "signup", "account",
+ "authentication", "password", "access", "auth", "session",
+ "authenticate", "credentials", "logout", "signout",
+
+ // Navigation/Site sections
+ "portal", "dashboard", "home", "welcome", "page", "site",
+ "secure", "member", "user", "profile", "settings", "menu",
+ "overview", "index", "main", "start", "landing",
+
+ // Marketing/Promotional
+ "free", "create", "new", "your", "special", "offer",
+ "deal", "discount", "promotion", "newsletter",
+
+ // Common website sections
+ "help", "support", "contact", "about", "faq", "terms",
+ "privacy", "cookie", "service", "services", "products",
+ "shop", "store", "cart", "checkout",
+
+ // Generic descriptors
+ "online", "web", "digital", "mobile", "my", "personal",
+ "private", "general", "default", "standard", "website",
+
+ // System/Technical
+ "system", "admin", "administrator", "platform",
+ "gateway", "api", "interface", "console",
+
+ // Time-related
+ "today", "now", "current", "latest", "newest", "recent",
+
+ // General
+ "the", "and", "or", "but", "to", "up",
+
+ // ═══════════════════════════════════════════════════════════════════════════════
+ // Dutch Stop Words
+ // ═══════════════════════════════════════════════════════════════════════════════
+
+ // Authentication related
+ "inloggen", "registreren", "registratie", "aanmelden",
+ "inschrijven", "uitloggen", "wachtwoord", "toegang",
+ "authenticatie",
+
+ // Navigation/Site sections
+ "portaal", "overzicht", "startpagina", "welkom", "pagina",
+ "beveiligd", "lid", "gebruiker", "profiel", "instellingen",
+ "begin", "hoofdpagina",
+
+ // Marketing/Promotional
+ "gratis", "nieuw", "jouw", "schrijf", "nieuwsbrief",
+ "aanbieding", "korting", "speciaal", "actie",
+
+ // Common website sections
+ "hulp", "ondersteuning", "voorwaarden",
+ "dienst", "diensten", "producten",
+ "winkel", "bestellen", "winkelwagen",
+
+ // Generic descriptors
+ "digitaal", "mobiel", "mijn", "persoonlijk",
+ "algemeen", "standaard",
+
+ // System/Technical
+ "systeem", "beheer", "beheerder",
+
+ // Time-related
+ "vandaag", "huidig", "nieuwste",
+
+ // General
+ "je", "in", "op", "de", "van", "ons", "allemaal",
+];
diff --git a/core/rust/src/credential_matcher/tests.rs b/core/rust/src/credential_matcher/tests.rs
new file mode 100644
index 000000000..54f68ed1a
--- /dev/null
+++ b/core/rust/src/credential_matcher/tests.rs
@@ -0,0 +1,390 @@
+//! Tests for credential matcher - ported from CredentialMatcher.test.ts
+
+use super::*;
+
+/// Helper function to create test credentials with standardized structure.
+fn create_test_credential(service_name: &str, service_url: &str, username: &str) -> Credential {
+ Credential {
+ id: uuid_v4(),
+ service_name: Some(service_name.to_string()),
+ service_url: if service_url.is_empty() {
+ None
+ } else {
+ Some(service_url.to_string())
+ },
+ username: if username.is_empty() {
+ None
+ } else {
+ Some(username.to_string())
+ },
+ }
+}
+
+/// Simple UUID v4 generator for tests
+fn uuid_v4() -> String {
+ use std::time::{SystemTime, UNIX_EPOCH};
+ let nanos = SystemTime::now()
+ .duration_since(UNIX_EPOCH)
+ .unwrap()
+ .as_nanos();
+ format!("{:032x}", nanos)
+}
+
+/// Creates the shared test credential dataset used across all platforms.
+fn create_shared_test_credentials() -> Vec {
+ vec![
+ create_test_credential("Gmail", "https://gmail.com", "user@gmail.com"),
+ create_test_credential("Google", "https://google.com", "user@google.com"),
+ create_test_credential("Coolblue", "https://www.coolblue.nl", "user@coolblue.nl"),
+ create_test_credential("Amazon", "https://amazon.com", "user@amazon.com"),
+ create_test_credential("Coolblue App", "com.coolblue.app", "user@coolblue.nl"),
+ create_test_credential("Dumpert", "dumpert.nl", "user@dumpert.nl"),
+ create_test_credential("GitHub", "github.com", "user@github.com"),
+ create_test_credential("Stack Overflow", "https://stackoverflow.com", "user@stackoverflow.com"),
+ create_test_credential("Subdomain Example", "https://app.example.com", "user@example.com"),
+ create_test_credential("Title Only newyorktimes", "", ""),
+ create_test_credential("Bank Account", "https://secure-bank.com", "user@bank.com"),
+ create_test_credential("AliExpress", "https://aliexpress.com", "user@aliexpress.com"),
+ create_test_credential("Reddit", "", "user@reddit.com"),
+ ]
+}
+
+fn filter(credentials: Vec, current_url: &str, page_title: &str) -> Vec {
+ let input = CredentialMatcherInput {
+ credentials,
+ current_url: current_url.to_string(),
+ page_title: page_title.to_string(),
+ matching_mode: AutofillMatchingMode::Default,
+ };
+ filter_credentials(input).credentials
+}
+
+// ═══════════════════════════════════════════════════════════════════════════════
+// Test cases ported from CredentialMatcher.test.ts
+// ═══════════════════════════════════════════════════════════════════════════════
+
+/// [#1] - Exact URL match
+#[test]
+fn test_exact_url_match() {
+ let credentials = create_shared_test_credentials();
+ let matches = filter(credentials, "www.coolblue.nl", "");
+
+ assert_eq!(matches.len(), 1);
+ assert_eq!(matches[0].service_name.as_deref(), Some("Coolblue"));
+}
+
+/// [#2] - Base URL with path match
+#[test]
+fn test_base_url_with_path_match() {
+ let credentials = create_shared_test_credentials();
+ let matches = filter(credentials, "https://gmail.com/signin", "");
+
+ assert_eq!(matches.len(), 1);
+ assert_eq!(matches[0].service_name.as_deref(), Some("Gmail"));
+}
+
+/// [#3] - Root domain with subdomain match
+#[test]
+fn test_root_domain_with_subdomain_match() {
+ let credentials = create_shared_test_credentials();
+ let matches = filter(credentials, "https://mail.google.com", "");
+
+ assert_eq!(matches.len(), 1);
+ assert_eq!(matches[0].service_name.as_deref(), Some("Google"));
+}
+
+/// [#4] - No matches for non-existent domain
+#[test]
+fn test_no_matches_for_nonexistent_domain() {
+ let credentials = create_shared_test_credentials();
+ let matches = filter(credentials, "https://nonexistent.com", "");
+
+ assert_eq!(matches.len(), 0);
+}
+
+/// [#5] - Partial URL stored matches full URL search
+#[test]
+fn test_partial_url_matches_full_url() {
+ let credentials = create_shared_test_credentials();
+ let matches = filter(credentials, "https://www.dumpert.nl", "");
+
+ assert_eq!(matches.len(), 1);
+ assert_eq!(matches[0].service_name.as_deref(), Some("Dumpert"));
+}
+
+/// [#6] - Full URL stored matches partial URL search
+#[test]
+fn test_full_url_matches_partial_url() {
+ let credentials = create_shared_test_credentials();
+ let matches = filter(credentials, "coolblue.nl", "");
+
+ assert_eq!(matches.len(), 1);
+ assert_eq!(matches[0].service_name.as_deref(), Some("Coolblue"));
+}
+
+/// [#7] - Protocol variations (http/https/none) match
+#[test]
+fn test_protocol_variations() {
+ let credentials = create_shared_test_credentials();
+
+ let https_matches = filter(credentials.clone(), "https://github.com", "");
+ let http_matches = filter(credentials.clone(), "http://github.com", "");
+ let no_protocol_matches = filter(credentials, "github.com", "");
+
+ assert_eq!(https_matches.len(), 1);
+ assert_eq!(http_matches.len(), 1);
+ assert_eq!(no_protocol_matches.len(), 1);
+ assert_eq!(https_matches[0].service_name.as_deref(), Some("GitHub"));
+ assert_eq!(http_matches[0].service_name.as_deref(), Some("GitHub"));
+ assert_eq!(no_protocol_matches[0].service_name.as_deref(), Some("GitHub"));
+}
+
+/// [#8] - WWW prefix variations match
+#[test]
+fn test_www_variations() {
+ let credentials = create_shared_test_credentials();
+
+ let with_www = filter(credentials.clone(), "https://www.dumpert.nl", "");
+ let without_www = filter(credentials, "https://dumpert.nl", "");
+
+ assert_eq!(with_www.len(), 1);
+ assert_eq!(without_www.len(), 1);
+ assert_eq!(with_www[0].service_name.as_deref(), Some("Dumpert"));
+ assert_eq!(without_www[0].service_name.as_deref(), Some("Dumpert"));
+}
+
+/// [#9] - Subdomain matching
+#[test]
+fn test_subdomain_matching() {
+ let credentials = create_shared_test_credentials();
+
+ let app_subdomain = filter(credentials.clone(), "https://app.example.com", "");
+ let www_subdomain = filter(credentials.clone(), "https://www.example.com", "");
+ let no_subdomain = filter(credentials, "https://example.com", "");
+
+ assert_eq!(app_subdomain.len(), 1);
+ assert_eq!(app_subdomain[0].service_name.as_deref(), Some("Subdomain Example"));
+ assert_eq!(www_subdomain.len(), 1);
+ assert_eq!(www_subdomain[0].service_name.as_deref(), Some("Subdomain Example"));
+ assert_eq!(no_subdomain.len(), 1);
+ assert_eq!(no_subdomain[0].service_name.as_deref(), Some("Subdomain Example"));
+}
+
+/// [#10] - Paths and query strings ignored
+#[test]
+fn test_paths_and_query_strings_ignored() {
+ let credentials = create_shared_test_credentials();
+
+ let with_path = filter(credentials.clone(), "https://github.com/user/repo", "");
+ let with_query = filter(credentials.clone(), "https://stackoverflow.com/questions?tab=newest", "");
+ let with_fragment = filter(credentials, "https://gmail.com#inbox", "");
+
+ assert_eq!(with_path.len(), 1);
+ assert_eq!(with_path[0].service_name.as_deref(), Some("GitHub"));
+ assert_eq!(with_query.len(), 1);
+ assert_eq!(with_query[0].service_name.as_deref(), Some("Stack Overflow"));
+ assert_eq!(with_fragment.len(), 1);
+ assert_eq!(with_fragment[0].service_name.as_deref(), Some("Gmail"));
+}
+
+/// [#11] - Complex URL variations
+#[test]
+fn test_complex_url_variations() {
+ let credentials = create_shared_test_credentials();
+ let matches = filter(credentials, "https://www.coolblue.nl/product/12345?ref=google", "");
+
+ assert_eq!(matches.len(), 1);
+ assert_eq!(matches[0].service_name.as_deref(), Some("Coolblue"));
+}
+
+/// [#12] - Priority ordering
+#[test]
+fn test_priority_ordering() {
+ let credentials = create_shared_test_credentials();
+ let matches = filter(credentials, "coolblue.nl", "");
+
+ assert_eq!(matches.len(), 1);
+ assert_eq!(matches[0].service_name.as_deref(), Some("Coolblue"));
+}
+
+/// [#13] - Title-only matching
+#[test]
+fn test_title_only_matching() {
+ let credentials = create_shared_test_credentials();
+ let matches = filter(credentials, "https://nomatch.com", "newyorktimes");
+
+ assert_eq!(matches.len(), 1);
+ assert_eq!(matches[0].service_name.as_deref(), Some("Title Only newyorktimes"));
+}
+
+/// [#14] - Domain name part matching
+#[test]
+fn test_domain_name_part_matching() {
+ let credentials = create_shared_test_credentials();
+ let matches = filter(credentials, "https://coolblue.be", "");
+
+ // coolblue.be should NOT match coolblue.nl
+ assert_eq!(matches.len(), 0);
+}
+
+/// [#15] - Package name matching
+#[test]
+fn test_package_name_matching() {
+ let credentials = create_shared_test_credentials();
+ let matches = filter(credentials, "com.coolblue.app", "");
+
+ assert_eq!(matches.len(), 1);
+ assert_eq!(matches[0].service_name.as_deref(), Some("Coolblue App"));
+}
+
+/// [#16] - Invalid URL handling
+#[test]
+fn test_invalid_url_handling() {
+ let credentials = create_shared_test_credentials();
+ let matches = filter(credentials, "not a url", "");
+
+ assert_eq!(matches.len(), 0);
+}
+
+/// [#17] - Anti-phishing protection
+#[test]
+fn test_anti_phishing_protection() {
+ let credentials = create_shared_test_credentials();
+ let matches = filter(credentials, "https://secure-bankk.com", "");
+
+ // Should NOT match secure-bank.com (different domain)
+ assert_eq!(matches.len(), 0);
+}
+
+/// [#18] - Ensure only full words are matched
+#[test]
+fn test_full_word_matching_only() {
+ let credentials = create_shared_test_credentials();
+ let matches = filter(credentials, "", "Express Yourself App | Description");
+
+ // The string above should not match "AliExpress" service name
+ assert_eq!(matches.len(), 0);
+}
+
+/// [#19] - Ensure separators and punctuation are stripped for matching
+#[test]
+fn test_separators_and_punctuation_stripped() {
+ let credentials = create_shared_test_credentials();
+ let matches = filter(credentials, "https://nomatch.com", "Reddit, social media platform");
+
+ // Should match "Reddit" even though it's followed by a comma and description
+ assert_eq!(matches.len(), 1);
+ assert_eq!(matches[0].service_name.as_deref(), Some("Reddit"));
+}
+
+/// [#20] - Test reversed domain (app package name) doesn't match on TLD
+#[test]
+fn test_reversed_domain_no_tld_match() {
+ let credentials = vec![
+ create_test_credential("Dumpert.nl", "", "user@dumpert.nl"),
+ create_test_credential("Marktplaats.nl", "", "user@marktplaats.nl"),
+ ];
+
+ let matches = filter(credentials, "nl.marktplaats.android", "");
+
+ // Should only match Marktplaats, not Dumpert (even though both have "nl")
+ assert_eq!(matches.len(), 1);
+ assert_eq!(matches[0].service_name.as_deref(), Some("Marktplaats.nl"));
+}
+
+/// [#21] - Test app package names are properly detected and handled
+#[test]
+fn test_app_package_names_handling() {
+ let credentials = vec![
+ create_test_credential("Google App", "com.google.android.googlequicksearchbox", "user@google.com"),
+ create_test_credential("Facebook", "com.facebook.katana", "user@facebook.com"),
+ create_test_credential("WhatsApp", "com.whatsapp", "user@whatsapp.com"),
+ create_test_credential("Generic Site", "example.com", "user@example.com"),
+ ];
+
+ // Test com.google.android package matches
+ let google_matches = filter(credentials.clone(), "com.google.android.googlequicksearchbox", "");
+ assert_eq!(google_matches.len(), 1);
+ assert_eq!(google_matches[0].service_name.as_deref(), Some("Google App"));
+
+ // Test com.facebook package matches
+ let facebook_matches = filter(credentials.clone(), "com.facebook.katana", "");
+ assert_eq!(facebook_matches.len(), 1);
+ assert_eq!(facebook_matches[0].service_name.as_deref(), Some("Facebook"));
+
+ // Test that web domain doesn't match package name
+ let web_matches = filter(credentials, "https://example.com", "");
+ assert_eq!(web_matches.len(), 1);
+ assert_eq!(web_matches[0].service_name.as_deref(), Some("Generic Site"));
+}
+
+/// [#22] - Test multi-part TLDs like .com.au don't match incorrectly
+#[test]
+fn test_multi_part_tlds() {
+ let credentials = vec![
+ create_test_credential("Example Site AU", "https://example.com.au", "user@example.com.au"),
+ create_test_credential("BlaBla AU", "https://blabla.blabla.com.au", "user@blabla.com.au"),
+ create_test_credential("Another AU", "https://another.com.au", "user@another.com.au"),
+ create_test_credential("UK Site", "https://example.co.uk", "user@example.co.uk"),
+ ];
+
+ // Test that blabla.blabla.com.au doesn't match other .com.au sites
+ let blabla_matches = filter(credentials.clone(), "https://blabla.blabla.com.au", "");
+ assert_eq!(blabla_matches.len(), 1);
+ assert_eq!(blabla_matches[0].service_name.as_deref(), Some("BlaBla AU"));
+
+ // Test that example.com.au doesn't match blabla.blabla.com.au
+ let example_matches = filter(credentials.clone(), "https://example.com.au", "");
+ assert_eq!(example_matches.len(), 1);
+ assert_eq!(example_matches[0].service_name.as_deref(), Some("Example Site AU"));
+
+ // Test that .co.uk domains work correctly too
+ let uk_matches = filter(credentials, "https://example.co.uk", "");
+ assert_eq!(uk_matches.len(), 1);
+ assert_eq!(uk_matches[0].service_name.as_deref(), Some("UK Site"));
+}
+
+/// Test JSON serialization/deserialization
+#[test]
+fn test_json_roundtrip() {
+ let credentials = create_shared_test_credentials();
+ let input = CredentialMatcherInput {
+ credentials,
+ current_url: "https://github.com".to_string(),
+ page_title: String::new(),
+ matching_mode: AutofillMatchingMode::Default,
+ };
+
+ let json = serde_json::to_string(&input).unwrap();
+ let output_json = filter_credentials_json(&json).unwrap();
+ let output: CredentialMatcherOutput = serde_json::from_str(&output_json).unwrap();
+
+ assert_eq!(output.credentials.len(), 1);
+ assert_eq!(output.credentials[0].service_name.as_deref(), Some("GitHub"));
+}
+
+/// Test empty URL returns empty results
+#[test]
+fn test_empty_url() {
+ let credentials = create_shared_test_credentials();
+ let matches = filter(credentials, "", "");
+
+ assert_eq!(matches.len(), 0);
+}
+
+/// Test max 3 results returned
+#[test]
+fn test_max_three_results() {
+ let credentials = vec![
+ create_test_credential("Site 1", "example.com", ""),
+ create_test_credential("Site 2", "sub1.example.com", ""),
+ create_test_credential("Site 3", "sub2.example.com", ""),
+ create_test_credential("Site 4", "sub3.example.com", ""),
+ create_test_credential("Site 5", "sub4.example.com", ""),
+ ];
+
+ let matches = filter(credentials, "https://example.com", "");
+
+ // Should return max 3 results
+ assert!(matches.len() <= 3);
+}
diff --git a/shared/rust-core/src/error.rs b/core/rust/src/error.rs
similarity index 100%
rename from shared/rust-core/src/error.rs
rename to core/rust/src/error.rs
diff --git a/core/rust/src/lib.rs b/core/rust/src/lib.rs
new file mode 100644
index 000000000..76d4764d0
--- /dev/null
+++ b/core/rust/src/lib.rs
@@ -0,0 +1,46 @@
+//! AliasVault Core Library
+//!
+//! Cross-platform core functionality for AliasVault, including:
+//! - **merge**: Vault merge using Last-Write-Wins (LWW) strategy
+//! - **credential_matcher**: Cross-platform credential filtering for autofill
+//!
+//! This library accepts data as JSON and returns results as JSON.
+//! Each platform (browser, iOS, Android, .NET) handles its own I/O
+//! and calls this library for the core logic.
+//!
+//! # Example (conceptual)
+//! ```ignore
+//! // Merge example
+//! let local_tables = read_all_tables_as_json(local_db);
+//! let server_tables = read_all_tables_as_json(server_db);
+//! let result = merge_vaults(local_tables, server_tables);
+//!
+//! // Credential matching example
+//! let credentials = get_credentials_json();
+//! let matches = filter_credentials(credentials, "https://github.com", "GitHub");
+//! ```
+
+pub mod error;
+pub mod merge;
+pub mod credential_matcher;
+
+pub use error::VaultError;
+pub use merge::{
+ merge_vaults, MergeInput, MergeOutput, MergeStats, SqlStatement, TableData,
+ SYNCABLE_TABLE_NAMES,
+};
+pub use credential_matcher::{
+ filter_credentials, extract_domain, extract_root_domain,
+ AutofillMatchingMode, CredentialMatcherInput, CredentialMatcherOutput,
+};
+
+// WASM bindings
+#[cfg(feature = "wasm")]
+pub mod wasm;
+
+#[cfg(feature = "wasm")]
+pub use wasm::*;
+
+// UniFFI scaffolding
+#[cfg(feature = "uniffi")]
+uniffi::setup_scaffolding!();
diff --git a/shared/rust-core/src/merge.rs b/core/rust/src/merge/mod.rs
similarity index 99%
rename from shared/rust-core/src/merge.rs
rename to core/rust/src/merge/mod.rs
index e993fc3e2..9f63077a8 100644
--- a/shared/rust-core/src/merge.rs
+++ b/core/rust/src/merge/mod.rs
@@ -3,12 +3,15 @@
//! This module provides the core merge functionality that works on JSON table data.
//! It generates SQL statements that clients can execute directly on their local database.
+mod types;
+
use chrono::{DateTime, Utc};
use serde::{Deserialize, Serialize};
use std::collections::HashMap;
use crate::error::VaultResult;
-use crate::types::SYNCABLE_TABLES;
+use types::SYNCABLE_TABLES;
+pub use types::SYNCABLE_TABLE_NAMES;
/// A record is a map of column names to JSON values.
pub type Record = HashMap;
@@ -320,12 +323,12 @@ fn merge_table_by_composite_key(
}
// Server-only records (by composite key) - generate INSERTs
- for (key, server_record) in &server_map {
+ for (_key, server_record) in &server_map {
stats.records_inserted += 1;
#[cfg(feature = "wasm")]
{
use crate::wasm::log;
- log(&format!("[merge_composite] SERVER ONLY (INSERT): key={}", key));
+ log(&format!("[merge_composite] SERVER ONLY (INSERT): key={}", _key));
}
if let Some(stmt) = generate_insert_sql(table_name, server_record) {
statements.push(stmt);
diff --git a/shared/rust-core/src/types.rs b/core/rust/src/merge/types.rs
similarity index 100%
rename from shared/rust-core/src/types.rs
rename to core/rust/src/merge/types.rs
diff --git a/core/rust/src/wasm.rs b/core/rust/src/wasm.rs
new file mode 100644
index 000000000..869feeeb8
--- /dev/null
+++ b/core/rust/src/wasm.rs
@@ -0,0 +1,80 @@
+//! WASM bindings for browser extension.
+
+use wasm_bindgen::prelude::*;
+
+use crate::credential_matcher::{
+ filter_credentials, CredentialMatcherInput, CredentialMatcherOutput,
+};
+use crate::merge::{merge_vaults, MergeInput, MergeOutput};
+
+#[wasm_bindgen]
+extern "C" {
+ #[wasm_bindgen(js_namespace = console)]
+ pub fn log(s: &str);
+}
+
+/// Initialize panic hook for better error messages.
+#[wasm_bindgen(start)]
+pub fn init() {
+ console_error_panic_hook::set_once();
+}
+
+/// Get the list of table names that need to be synced.
+#[wasm_bindgen(js_name = getSyncableTableNames)]
+pub fn get_syncable_table_names() -> Vec {
+ crate::merge::SYNCABLE_TABLE_NAMES
+ .iter()
+ .map(|s| s.to_string())
+ .collect()
+}
+
+/// Merge vaults using LWW strategy.
+///
+/// Takes a JsValue (MergeInput) and returns a JsValue (MergeOutput).
+#[wasm_bindgen(js_name = mergeVaults)]
+pub fn merge_vaults_js(input: JsValue) -> Result {
+ let input: MergeInput = serde_wasm_bindgen::from_value(input)
+ .map_err(|e| JsValue::from_str(&format!("Failed to parse input: {}", e)))?;
+
+ let output: MergeOutput = merge_vaults(input)
+ .map_err(|e| JsValue::from_str(&format!("Merge failed: {}", e)))?;
+
+ serde_wasm_bindgen::to_value(&output)
+ .map_err(|e| JsValue::from_str(&format!("Failed to serialize output: {}", e)))
+}
+
+/// Merge vaults using JSON strings (alternative API).
+///
+/// Takes a JSON string and returns a JSON string.
+#[wasm_bindgen(js_name = mergeVaultsJson)]
+pub fn merge_vaults_json_js(input_json: &str) -> Result {
+ crate::merge::merge_vaults_json(input_json)
+ .map_err(|e| JsValue::from_str(&format!("Merge failed: {}", e)))
+}
+
+// ═══════════════════════════════════════════════════════════════════════════════
+// Credential Matcher WASM Bindings
+// ═══════════════════════════════════════════════════════════════════════════════
+
+/// Filter credentials for autofill.
+///
+/// Takes a JsValue (CredentialMatcherInput) and returns a JsValue (CredentialMatcherOutput).
+#[wasm_bindgen(js_name = filterCredentials)]
+pub fn filter_credentials_js(input: JsValue) -> Result {
+ let input: CredentialMatcherInput = serde_wasm_bindgen::from_value(input)
+ .map_err(|e| JsValue::from_str(&format!("Failed to parse input: {}", e)))?;
+
+ let output: CredentialMatcherOutput = filter_credentials(input);
+
+ serde_wasm_bindgen::to_value(&output)
+ .map_err(|e| JsValue::from_str(&format!("Failed to serialize output: {}", e)))
+}
+
+/// Filter credentials using JSON strings (alternative API).
+///
+/// Takes a JSON string and returns a JSON string.
+#[wasm_bindgen(js_name = filterCredentialsJson)]
+pub fn filter_credentials_json_js(input_json: &str) -> Result {
+ crate::credential_matcher::filter_credentials_json(input_json)
+ .map_err(|e| JsValue::from_str(&e))
+}
diff --git a/shared/identity-generator/build.sh b/core/typescript/identity-generator/build.sh
similarity index 66%
rename from shared/identity-generator/build.sh
rename to core/typescript/identity-generator/build.sh
index b39f9c2e7..25601784b 100755
--- a/shared/identity-generator/build.sh
+++ b/core/typescript/identity-generator/build.sh
@@ -5,9 +5,9 @@ set -u # Treat unset variables as errors
# Define output targets for identity-generator
TARGETS=(
- "../../apps/browser-extension/src/utils/dist/shared/identity-generator"
- "../../apps/mobile-app/utils/dist/shared/identity-generator"
- "../../apps/server/AliasVault.Client/wwwroot/js/dist/shared/identity-generator"
+ "../../../apps/browser-extension/src/utils/dist/core/identity-generator"
+ "../../../apps/mobile-app/utils/dist/core/identity-generator"
+ "../../../apps/server/AliasVault.Client/wwwroot/js/dist/core/identity-generator"
)
# Build and distribute identity-generator
@@ -38,12 +38,12 @@ for target in "${TARGETS[@]}"; do
cat > "$target/README.md" < "$target/README.md" < "$target/README.md" < /dev/null; then
- echo "📦 Building rust-core (Rust toolchain detected)..."
- echo " Note: Browser extension uses TypeScript implementation"
- ./build.sh --csharp # Build for .NET by default on dev machines
-else
- echo "⚠️ Skipping rust-core build (Rust not installed)"
- echo " Install Rust from https://rustup.rs to enable Rust core builds"
-fi
-
-echo "✅ All builds completed successfully."
diff --git a/shared/rust-core/src/lib.rs b/shared/rust-core/src/lib.rs
deleted file mode 100644
index b78ee571c..000000000
--- a/shared/rust-core/src/lib.rs
+++ /dev/null
@@ -1,42 +0,0 @@
-//! AliasVault Core Library
-//!
-//! Cross-platform merge logic for AliasVault using Last-Write-Wins (LWW) strategy.
-//!
-//! This library accepts table data as JSON and returns merged results as JSON.
-//! Each platform (browser, iOS, Android, .NET) handles its own SQLite I/O
-//! and calls this library for the merge logic.
-//!
-//! # Example (conceptual)
-//! ```ignore
-//! // Platform reads tables from local and server SQLite databases
-//! let local_tables = read_all_tables_as_json(local_db);
-//! let server_tables = read_all_tables_as_json(server_db);
-//!
-//! // Rust performs the merge
-//! let result = merge_vaults(local_tables, server_tables);
-//!
-//! // Platform applies changes to local database
-//! apply_updates(local_db, result.updates);
-//! apply_inserts(local_db, result.inserts);
-//! ```
-
-pub mod error;
-pub mod merge;
-pub mod types;
-
-pub use error::VaultError;
-pub use merge::{
- merge_vaults, MergeInput, MergeOutput, MergeStats, SqlStatement, TableData,
-};
-pub use types::SYNCABLE_TABLE_NAMES;
-
-// WASM bindings
-#[cfg(feature = "wasm")]
-pub mod wasm;
-
-#[cfg(feature = "wasm")]
-pub use wasm::*;
-
-// UniFFI scaffolding
-#[cfg(feature = "uniffi")]
-uniffi::setup_scaffolding!();
diff --git a/shared/rust-core/src/wasm.rs b/shared/rust-core/src/wasm.rs
deleted file mode 100644
index f7f08df74..000000000
--- a/shared/rust-core/src/wasm.rs
+++ /dev/null
@@ -1,50 +0,0 @@
-//! WASM bindings for browser extension.
-
-use wasm_bindgen::prelude::*;
-
-use crate::merge::{merge_vaults, MergeInput, MergeOutput};
-
-#[wasm_bindgen]
-extern "C" {
- #[wasm_bindgen(js_namespace = console)]
- pub fn log(s: &str);
-}
-
-/// Initialize panic hook for better error messages.
-#[wasm_bindgen(start)]
-pub fn init() {
- console_error_panic_hook::set_once();
-}
-
-/// Get the list of table names that need to be synced.
-#[wasm_bindgen(js_name = getSyncableTableNames)]
-pub fn get_syncable_table_names() -> Vec {
- crate::types::SYNCABLE_TABLE_NAMES
- .iter()
- .map(|s| s.to_string())
- .collect()
-}
-
-/// Merge vaults using LWW strategy.
-///
-/// Takes a JsValue (MergeInput) and returns a JsValue (MergeOutput).
-#[wasm_bindgen(js_name = mergeVaults)]
-pub fn merge_vaults_js(input: JsValue) -> Result {
- let input: MergeInput = serde_wasm_bindgen::from_value(input)
- .map_err(|e| JsValue::from_str(&format!("Failed to parse input: {}", e)))?;
-
- let output: MergeOutput = merge_vaults(input)
- .map_err(|e| JsValue::from_str(&format!("Merge failed: {}", e)))?;
-
- serde_wasm_bindgen::to_value(&output)
- .map_err(|e| JsValue::from_str(&format!("Failed to serialize output: {}", e)))
-}
-
-/// Merge vaults using JSON strings (alternative API).
-///
-/// Takes a JSON string and returns a JSON string.
-#[wasm_bindgen(js_name = mergeVaultsJson)]
-pub fn merge_vaults_json_js(input_json: &str) -> Result {
- crate::merge::merge_vaults_json(input_json)
- .map_err(|e| JsValue::from_str(&format!("Merge failed: {}", e)))
-}