@haex-space/vault-sdk 2.3.8 → 2.3.12

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
File without changes
@@ -1,4 +1,4 @@
1
- import { D as DatabaseQueryResult, M as Migration, b as MigrationResult, W as WebRequestOptions, c as WebResponse, H as HaexHubConfig, a as ExtensionInfo, A as ApplicationContext, d as DatabasePermissionRequest, P as PermissionResponse, S as SearchResult, e as EventCallback } from './types-FE9ewl3r.js';
1
+ import { D as DatabaseQueryResult, M as Migration, b as MigrationResult, W as WebRequestOptions, c as WebResponse, H as HaexHubConfig, a as ExtensionInfo, A as ApplicationContext, d as DatabasePermissionRequest, P as PermissionResponse, S as SearchResult, e as ExternalRequestHandler, f as ExternalResponse, g as EventCallback } from './types-DBF83o_W.mjs';
2
2
  import { SqliteRemoteDatabase } from 'drizzle-orm/sqlite-proxy';
3
3
 
4
4
  declare class StorageAPI {
@@ -185,6 +185,7 @@ declare class HaexVaultClient {
185
185
  private config;
186
186
  private pendingRequests;
187
187
  private eventListeners;
188
+ private externalRequestHandlers;
188
189
  private messageHandler;
189
190
  private initialized;
190
191
  private requestCounter;
@@ -280,6 +281,31 @@ declare class HaexVaultClient {
280
281
  requestDatabasePermission(request: DatabasePermissionRequest): Promise<PermissionResponse>;
281
282
  checkDatabasePermission(resource: string, operation: "read" | "write"): Promise<boolean>;
282
283
  respondToSearch(requestId: string, results: SearchResult[]): Promise<void>;
284
+ /**
285
+ * Register a handler for external requests (from browser extensions, CLI, servers, etc.)
286
+ *
287
+ * @param action - The action/method name to handle (e.g., "get-logins", "get-totp")
288
+ * @param handler - Function that processes the request and returns a response
289
+ * @returns Unsubscribe function to remove the handler
290
+ *
291
+ * @example
292
+ * ```typescript
293
+ * client.onExternalRequest("get-logins", async (request) => {
294
+ * const entries = await getMatchingEntries(request.payload.url);
295
+ * return {
296
+ * requestId: request.requestId,
297
+ * success: true,
298
+ * data: { entries }
299
+ * };
300
+ * });
301
+ * ```
302
+ */
303
+ onExternalRequest(action: string, handler: ExternalRequestHandler): () => void;
304
+ /**
305
+ * Send a response to an external request back to haex-vault
306
+ * This is called internally after a handler processes a request
307
+ */
308
+ respondToExternalRequest(response: ExternalResponse): Promise<void>;
283
309
  request<T = unknown>(method: string, params?: Record<string, unknown>): Promise<T>;
284
310
  private postMessage;
285
311
  private invoke;
@@ -289,6 +315,7 @@ declare class HaexVaultClient {
289
315
  private init;
290
316
  private handleMessage;
291
317
  private handleEvent;
318
+ private handleExternalRequest;
292
319
  private emitEvent;
293
320
  private generateRequestId;
294
321
  private validatePublicKey;
@@ -1,4 +1,4 @@
1
- import { D as DatabaseQueryResult, M as Migration, b as MigrationResult, W as WebRequestOptions, c as WebResponse, H as HaexHubConfig, a as ExtensionInfo, A as ApplicationContext, d as DatabasePermissionRequest, P as PermissionResponse, S as SearchResult, e as EventCallback } from './types-FE9ewl3r.mjs';
1
+ import { D as DatabaseQueryResult, M as Migration, b as MigrationResult, W as WebRequestOptions, c as WebResponse, H as HaexHubConfig, a as ExtensionInfo, A as ApplicationContext, d as DatabasePermissionRequest, P as PermissionResponse, S as SearchResult, e as ExternalRequestHandler, f as ExternalResponse, g as EventCallback } from './types-DBF83o_W.js';
2
2
  import { SqliteRemoteDatabase } from 'drizzle-orm/sqlite-proxy';
3
3
 
4
4
  declare class StorageAPI {
@@ -185,6 +185,7 @@ declare class HaexVaultClient {
185
185
  private config;
186
186
  private pendingRequests;
187
187
  private eventListeners;
188
+ private externalRequestHandlers;
188
189
  private messageHandler;
189
190
  private initialized;
190
191
  private requestCounter;
@@ -280,6 +281,31 @@ declare class HaexVaultClient {
280
281
  requestDatabasePermission(request: DatabasePermissionRequest): Promise<PermissionResponse>;
281
282
  checkDatabasePermission(resource: string, operation: "read" | "write"): Promise<boolean>;
282
283
  respondToSearch(requestId: string, results: SearchResult[]): Promise<void>;
284
+ /**
285
+ * Register a handler for external requests (from browser extensions, CLI, servers, etc.)
286
+ *
287
+ * @param action - The action/method name to handle (e.g., "get-logins", "get-totp")
288
+ * @param handler - Function that processes the request and returns a response
289
+ * @returns Unsubscribe function to remove the handler
290
+ *
291
+ * @example
292
+ * ```typescript
293
+ * client.onExternalRequest("get-logins", async (request) => {
294
+ * const entries = await getMatchingEntries(request.payload.url);
295
+ * return {
296
+ * requestId: request.requestId,
297
+ * success: true,
298
+ * data: { entries }
299
+ * };
300
+ * });
301
+ * ```
302
+ */
303
+ onExternalRequest(action: string, handler: ExternalRequestHandler): () => void;
304
+ /**
305
+ * Send a response to an external request back to haex-vault
306
+ * This is called internally after a handler processes a request
307
+ */
308
+ respondToExternalRequest(response: ExternalResponse): Promise<void>;
283
309
  request<T = unknown>(method: string, params?: Record<string, unknown>): Promise<T>;
284
310
  private postMessage;
285
311
  private invoke;
@@ -289,6 +315,7 @@ declare class HaexVaultClient {
289
315
  private init;
290
316
  private handleMessage;
291
317
  private handleEvent;
318
+ private handleExternalRequest;
292
319
  private emitEvent;
293
320
  private generateRequestId;
294
321
  private validatePublicKey;
package/dist/index.d.mts CHANGED
@@ -1,7 +1,7 @@
1
- import { H as HaexVaultClient } from './client-BIiJwbdW.mjs';
2
- export { D as DatabaseAPI, F as FilesystemAPI, P as PermissionsAPI, W as WebAPI } from './client-BIiJwbdW.mjs';
3
- import { E as ExtensionManifest, H as HaexHubConfig } from './types-FE9ewl3r.mjs';
4
- export { A as ApplicationContext, C as ContextChangedEvent, r as DEFAULT_TIMEOUT, m as DatabaseColumnInfo, k as DatabaseExecuteParams, i as DatabasePermission, d as DatabasePermissionRequest, j as DatabaseQueryParams, D as DatabaseQueryResult, l as DatabaseTableInfo, q as ErrorCode, e as EventCallback, a as ExtensionInfo, u as HAEXTENSION_EVENTS, t as HaexHubError, h as HaexHubEvent, f as HaexHubRequest, g as HaexHubResponse, v as HaextensionEvent, P as PermissionResponse, p as PermissionStatus, n as SearchQuery, o as SearchRequestEvent, S as SearchResult, T as TABLE_SEPARATOR, W as WebRequestOptions, c as WebResponse, s as getTableName } from './types-FE9ewl3r.mjs';
1
+ import { H as HaexVaultClient } from './client-BdeVsDdi.mjs';
2
+ export { D as DatabaseAPI, F as FilesystemAPI, P as PermissionsAPI, W as WebAPI } from './client-BdeVsDdi.mjs';
3
+ import { E as ExtensionManifest, H as HaexHubConfig } from './types-DBF83o_W.mjs';
4
+ export { A as ApplicationContext, C as ContextChangedEvent, v as DEFAULT_TIMEOUT, o as DatabaseColumnInfo, m as DatabaseExecuteParams, k as DatabasePermission, d as DatabasePermissionRequest, l as DatabaseQueryParams, D as DatabaseQueryResult, n as DatabaseTableInfo, u as ErrorCode, g as EventCallback, a as ExtensionInfo, s as ExternalRequest, r as ExternalRequestEvent, e as ExternalRequestHandler, f as ExternalResponse, y as HAEXTENSION_EVENTS, x as HaexHubError, j as HaexHubEvent, h as HaexHubRequest, i as HaexHubResponse, z as HaextensionEvent, P as PermissionResponse, t as PermissionStatus, p as SearchQuery, q as SearchRequestEvent, S as SearchResult, T as TABLE_SEPARATOR, W as WebRequestOptions, c as WebResponse, w as getTableName } from './types-DBF83o_W.mjs';
5
5
  export { H as HaextensionConfig } from './config-D_HXjsEV.mjs';
6
6
  import 'drizzle-orm/sqlite-proxy';
7
7
 
@@ -190,6 +190,67 @@ declare function hexToBytes(hex: string): ArrayBuffer;
190
190
  */
191
191
  declare function verifyExtensionSignature(files: ZipFileEntry[], manifest: ExtensionManifest): Promise<VerifyResult>;
192
192
 
193
+ /**
194
+ * Crypto utilities for Vault Key Management
195
+ * Implements PBKDF2 + AES-GCM encryption/decryption
196
+ *
197
+ * Used for:
198
+ * - Encrypting/decrypting vault names with server password
199
+ * - Encrypting/decrypting vault keys with vault password
200
+ * - Encrypting/decrypting CRDT data with vault key
201
+ */
202
+ /**
203
+ * Derives a cryptographic key from a password using PBKDF2
204
+ */
205
+ declare function deriveKeyFromPassword(password: string, salt: Uint8Array): Promise<CryptoKey>;
206
+ /**
207
+ * Generates a random vault key (32 bytes)
208
+ */
209
+ declare function generateVaultKey(): Uint8Array;
210
+ /**
211
+ * Encrypts a string (like vault name) with a password-derived key
212
+ * Returns: { encryptedData, nonce } as Base64 strings
213
+ */
214
+ declare function encryptString(data: string, derivedKey: CryptoKey): Promise<{
215
+ encryptedData: string;
216
+ nonce: string;
217
+ }>;
218
+ /**
219
+ * Decrypts a string (like vault name) with a password-derived key
220
+ */
221
+ declare function decryptString(encryptedData: string, nonce: string, derivedKey: CryptoKey): Promise<string>;
222
+ /**
223
+ * Encrypts the vault key with a password-derived key
224
+ * Returns: { encryptedVaultKey, salt, vaultKeyNonce } all as Base64 strings
225
+ */
226
+ declare function encryptVaultKey(vaultKey: Uint8Array, password: string): Promise<{
227
+ encryptedVaultKey: string;
228
+ salt: string;
229
+ vaultKeyNonce: string;
230
+ }>;
231
+ /**
232
+ * Decrypts the vault key using the password
233
+ */
234
+ declare function decryptVaultKey(encryptedVaultKey: string, salt: string, vaultKeyNonce: string, password: string): Promise<Uint8Array>;
235
+ /**
236
+ * Decrypts a vault name using the server password
237
+ * Convenience function that combines key derivation and decryption
238
+ */
239
+ declare function decryptVaultName(encryptedVaultName: string, vaultNameNonce: string, vaultNameSalt: string, password: string): Promise<string>;
240
+ /**
241
+ * Encrypts CRDT log data with the vault key
242
+ */
243
+ declare function encryptCrdtData(data: object, vaultKey: Uint8Array): Promise<{
244
+ encryptedData: string;
245
+ nonce: string;
246
+ }>;
247
+ /**
248
+ * Decrypts CRDT log data with the vault key
249
+ */
250
+ declare function decryptCrdtData<T = object>(encryptedData: string, nonce: string, vaultKey: Uint8Array): Promise<T>;
251
+ declare function arrayBufferToBase64(buffer: ArrayBuffer | Uint8Array): string;
252
+ declare function base64ToArrayBuffer(base64: string): Uint8Array;
253
+
193
254
  declare function createHaexVaultClient(config?: HaexHubConfig): HaexVaultClient;
194
255
 
195
- export { ExtensionManifest, HAEXSPACE_MESSAGE_TYPES, HAEXTENSION_METHODS, HaexHubConfig, HaexVaultClient, type HaexspaceMessageType, type HaextensionMethod, type VerifyResult, type ZipFileEntry, createHaexVaultClient, hexToBytes, installBaseTag, installCookiePolyfill, installHistoryPolyfill, installLocalStoragePolyfill, installPolyfills, installSessionStoragePolyfill, sortObjectKeysRecursively, verifyExtensionSignature };
256
+ export { ExtensionManifest, HAEXSPACE_MESSAGE_TYPES, HAEXTENSION_METHODS, HaexHubConfig, HaexVaultClient, type HaexspaceMessageType, type HaextensionMethod, type VerifyResult, type ZipFileEntry, arrayBufferToBase64, base64ToArrayBuffer, createHaexVaultClient, decryptCrdtData, decryptString, decryptVaultKey, decryptVaultName, deriveKeyFromPassword, encryptCrdtData, encryptString, encryptVaultKey, generateVaultKey, hexToBytes, installBaseTag, installCookiePolyfill, installHistoryPolyfill, installLocalStoragePolyfill, installPolyfills, installSessionStoragePolyfill, sortObjectKeysRecursively, verifyExtensionSignature };
package/dist/index.d.ts CHANGED
@@ -1,7 +1,7 @@
1
- import { H as HaexVaultClient } from './client-D4hDL-PR.js';
2
- export { D as DatabaseAPI, F as FilesystemAPI, P as PermissionsAPI, W as WebAPI } from './client-D4hDL-PR.js';
3
- import { E as ExtensionManifest, H as HaexHubConfig } from './types-FE9ewl3r.js';
4
- export { A as ApplicationContext, C as ContextChangedEvent, r as DEFAULT_TIMEOUT, m as DatabaseColumnInfo, k as DatabaseExecuteParams, i as DatabasePermission, d as DatabasePermissionRequest, j as DatabaseQueryParams, D as DatabaseQueryResult, l as DatabaseTableInfo, q as ErrorCode, e as EventCallback, a as ExtensionInfo, u as HAEXTENSION_EVENTS, t as HaexHubError, h as HaexHubEvent, f as HaexHubRequest, g as HaexHubResponse, v as HaextensionEvent, P as PermissionResponse, p as PermissionStatus, n as SearchQuery, o as SearchRequestEvent, S as SearchResult, T as TABLE_SEPARATOR, W as WebRequestOptions, c as WebResponse, s as getTableName } from './types-FE9ewl3r.js';
1
+ import { H as HaexVaultClient } from './client-Ctv_qXuk.js';
2
+ export { D as DatabaseAPI, F as FilesystemAPI, P as PermissionsAPI, W as WebAPI } from './client-Ctv_qXuk.js';
3
+ import { E as ExtensionManifest, H as HaexHubConfig } from './types-DBF83o_W.js';
4
+ export { A as ApplicationContext, C as ContextChangedEvent, v as DEFAULT_TIMEOUT, o as DatabaseColumnInfo, m as DatabaseExecuteParams, k as DatabasePermission, d as DatabasePermissionRequest, l as DatabaseQueryParams, D as DatabaseQueryResult, n as DatabaseTableInfo, u as ErrorCode, g as EventCallback, a as ExtensionInfo, s as ExternalRequest, r as ExternalRequestEvent, e as ExternalRequestHandler, f as ExternalResponse, y as HAEXTENSION_EVENTS, x as HaexHubError, j as HaexHubEvent, h as HaexHubRequest, i as HaexHubResponse, z as HaextensionEvent, P as PermissionResponse, t as PermissionStatus, p as SearchQuery, q as SearchRequestEvent, S as SearchResult, T as TABLE_SEPARATOR, W as WebRequestOptions, c as WebResponse, w as getTableName } from './types-DBF83o_W.js';
5
5
  export { H as HaextensionConfig } from './config-D_HXjsEV.js';
6
6
  import 'drizzle-orm/sqlite-proxy';
7
7
 
@@ -190,6 +190,67 @@ declare function hexToBytes(hex: string): ArrayBuffer;
190
190
  */
191
191
  declare function verifyExtensionSignature(files: ZipFileEntry[], manifest: ExtensionManifest): Promise<VerifyResult>;
192
192
 
193
+ /**
194
+ * Crypto utilities for Vault Key Management
195
+ * Implements PBKDF2 + AES-GCM encryption/decryption
196
+ *
197
+ * Used for:
198
+ * - Encrypting/decrypting vault names with server password
199
+ * - Encrypting/decrypting vault keys with vault password
200
+ * - Encrypting/decrypting CRDT data with vault key
201
+ */
202
+ /**
203
+ * Derives a cryptographic key from a password using PBKDF2
204
+ */
205
+ declare function deriveKeyFromPassword(password: string, salt: Uint8Array): Promise<CryptoKey>;
206
+ /**
207
+ * Generates a random vault key (32 bytes)
208
+ */
209
+ declare function generateVaultKey(): Uint8Array;
210
+ /**
211
+ * Encrypts a string (like vault name) with a password-derived key
212
+ * Returns: { encryptedData, nonce } as Base64 strings
213
+ */
214
+ declare function encryptString(data: string, derivedKey: CryptoKey): Promise<{
215
+ encryptedData: string;
216
+ nonce: string;
217
+ }>;
218
+ /**
219
+ * Decrypts a string (like vault name) with a password-derived key
220
+ */
221
+ declare function decryptString(encryptedData: string, nonce: string, derivedKey: CryptoKey): Promise<string>;
222
+ /**
223
+ * Encrypts the vault key with a password-derived key
224
+ * Returns: { encryptedVaultKey, salt, vaultKeyNonce } all as Base64 strings
225
+ */
226
+ declare function encryptVaultKey(vaultKey: Uint8Array, password: string): Promise<{
227
+ encryptedVaultKey: string;
228
+ salt: string;
229
+ vaultKeyNonce: string;
230
+ }>;
231
+ /**
232
+ * Decrypts the vault key using the password
233
+ */
234
+ declare function decryptVaultKey(encryptedVaultKey: string, salt: string, vaultKeyNonce: string, password: string): Promise<Uint8Array>;
235
+ /**
236
+ * Decrypts a vault name using the server password
237
+ * Convenience function that combines key derivation and decryption
238
+ */
239
+ declare function decryptVaultName(encryptedVaultName: string, vaultNameNonce: string, vaultNameSalt: string, password: string): Promise<string>;
240
+ /**
241
+ * Encrypts CRDT log data with the vault key
242
+ */
243
+ declare function encryptCrdtData(data: object, vaultKey: Uint8Array): Promise<{
244
+ encryptedData: string;
245
+ nonce: string;
246
+ }>;
247
+ /**
248
+ * Decrypts CRDT log data with the vault key
249
+ */
250
+ declare function decryptCrdtData<T = object>(encryptedData: string, nonce: string, vaultKey: Uint8Array): Promise<T>;
251
+ declare function arrayBufferToBase64(buffer: ArrayBuffer | Uint8Array): string;
252
+ declare function base64ToArrayBuffer(base64: string): Uint8Array;
253
+
193
254
  declare function createHaexVaultClient(config?: HaexHubConfig): HaexVaultClient;
194
255
 
195
- export { ExtensionManifest, HAEXSPACE_MESSAGE_TYPES, HAEXTENSION_METHODS, HaexHubConfig, HaexVaultClient, type HaexspaceMessageType, type HaextensionMethod, type VerifyResult, type ZipFileEntry, createHaexVaultClient, hexToBytes, installBaseTag, installCookiePolyfill, installHistoryPolyfill, installLocalStoragePolyfill, installPolyfills, installSessionStoragePolyfill, sortObjectKeysRecursively, verifyExtensionSignature };
256
+ export { ExtensionManifest, HAEXSPACE_MESSAGE_TYPES, HAEXTENSION_METHODS, HaexHubConfig, HaexVaultClient, type HaexspaceMessageType, type HaextensionMethod, type VerifyResult, type ZipFileEntry, arrayBufferToBase64, base64ToArrayBuffer, createHaexVaultClient, decryptCrdtData, decryptString, decryptVaultKey, decryptVaultName, deriveKeyFromPassword, encryptCrdtData, encryptString, encryptVaultKey, generateVaultKey, hexToBytes, installBaseTag, installCookiePolyfill, installHistoryPolyfill, installLocalStoragePolyfill, installPolyfills, installSessionStoragePolyfill, sortObjectKeysRecursively, verifyExtensionSignature };
package/dist/index.js CHANGED
@@ -375,7 +375,9 @@ var HAEXTENSION_EVENTS = {
375
375
  /** Context (theme, locale, platform) has changed */
376
376
  CONTEXT_CHANGED: "haextension:context:changed",
377
377
  /** Search request from HaexHub */
378
- SEARCH_REQUEST: "haextension:search:request"
378
+ SEARCH_REQUEST: "haextension:search:request",
379
+ /** External request from authorized client (browser extension, CLI, server, etc.) */
380
+ EXTERNAL_REQUEST: "haextension:external:request"
379
381
  };
380
382
 
381
383
  // src/methods.ts
@@ -818,6 +820,7 @@ var HaexVaultClient = class {
818
820
  constructor(config = {}) {
819
821
  this.pendingRequests = /* @__PURE__ */ new Map();
820
822
  this.eventListeners = /* @__PURE__ */ new Map();
823
+ this.externalRequestHandlers = /* @__PURE__ */ new Map();
821
824
  this.messageHandler = null;
822
825
  this.initialized = false;
823
826
  this.requestCounter = 0;
@@ -1080,6 +1083,40 @@ var HaexVaultClient = class {
1080
1083
  results
1081
1084
  });
1082
1085
  }
1086
+ /**
1087
+ * Register a handler for external requests (from browser extensions, CLI, servers, etc.)
1088
+ *
1089
+ * @param action - The action/method name to handle (e.g., "get-logins", "get-totp")
1090
+ * @param handler - Function that processes the request and returns a response
1091
+ * @returns Unsubscribe function to remove the handler
1092
+ *
1093
+ * @example
1094
+ * ```typescript
1095
+ * client.onExternalRequest("get-logins", async (request) => {
1096
+ * const entries = await getMatchingEntries(request.payload.url);
1097
+ * return {
1098
+ * requestId: request.requestId,
1099
+ * success: true,
1100
+ * data: { entries }
1101
+ * };
1102
+ * });
1103
+ * ```
1104
+ */
1105
+ onExternalRequest(action, handler) {
1106
+ this.externalRequestHandlers.set(action, handler);
1107
+ this.log(`[ExternalRequest] Registered handler for action: ${action}`);
1108
+ return () => {
1109
+ this.externalRequestHandlers.delete(action);
1110
+ this.log(`[ExternalRequest] Unregistered handler for action: ${action}`);
1111
+ };
1112
+ }
1113
+ /**
1114
+ * Send a response to an external request back to haex-vault
1115
+ * This is called internally after a handler processes a request
1116
+ */
1117
+ async respondToExternalRequest(response) {
1118
+ await this.request("external.respond", response);
1119
+ }
1083
1120
  async request(method, params = {}) {
1084
1121
  if (this.isNativeWindow && typeof window.__TAURI__ !== "undefined") {
1085
1122
  return this.invoke(method, params);
@@ -1177,6 +1214,13 @@ var HaexVaultClient = class {
1177
1214
  extensionVersion: params.extensionVersion,
1178
1215
  migrations: params.migrations
1179
1216
  });
1217
+ case "external.respond":
1218
+ return invoke("webview_extension_external_respond", {
1219
+ requestId: params.requestId,
1220
+ success: params.success,
1221
+ data: params.data,
1222
+ error: params.error
1223
+ });
1180
1224
  default:
1181
1225
  throw new HaexHubError(
1182
1226
  "METHOD_NOT_FOUND" /* METHOD_NOT_FOUND */,
@@ -1245,6 +1289,22 @@ var HaexVaultClient = class {
1245
1289
  console.error("[HaexSpace SDK] Failed to setup context change listener:", error);
1246
1290
  this.log("Failed to setup context change listener:", error);
1247
1291
  }
1292
+ try {
1293
+ await listen(HAEXTENSION_EVENTS.EXTERNAL_REQUEST, (event) => {
1294
+ this.log("Received external request event:", event);
1295
+ if (event.payload) {
1296
+ this.handleEvent({
1297
+ type: HAEXTENSION_EVENTS.EXTERNAL_REQUEST,
1298
+ data: event.payload,
1299
+ timestamp: Date.now()
1300
+ });
1301
+ }
1302
+ });
1303
+ console.log("[HaexSpace SDK] External request listener registered successfully");
1304
+ } catch (error) {
1305
+ console.error("[HaexSpace SDK] Failed to setup external request listener:", error);
1306
+ this.log("Failed to setup external request listener:", error);
1307
+ }
1248
1308
  this.resolveReady();
1249
1309
  return;
1250
1310
  }
@@ -1366,8 +1426,38 @@ postMessage error: ${e}`);
1366
1426
  this.log("Context updated:", this._context);
1367
1427
  this.notifySubscribers();
1368
1428
  }
1429
+ if (event.type === HAEXTENSION_EVENTS.EXTERNAL_REQUEST) {
1430
+ const externalEvent = event;
1431
+ this.handleExternalRequest(externalEvent.data);
1432
+ return;
1433
+ }
1369
1434
  this.emitEvent(event);
1370
1435
  }
1436
+ async handleExternalRequest(request) {
1437
+ this.log(`[ExternalRequest] Received request: ${request.action} from ${request.publicKey.substring(0, 20)}...`);
1438
+ const handler = this.externalRequestHandlers.get(request.action);
1439
+ if (!handler) {
1440
+ this.log(`[ExternalRequest] No handler for action: ${request.action}`);
1441
+ await this.respondToExternalRequest({
1442
+ requestId: request.requestId,
1443
+ success: false,
1444
+ error: `No handler registered for action: ${request.action}`
1445
+ });
1446
+ return;
1447
+ }
1448
+ try {
1449
+ const response = await handler(request);
1450
+ await this.respondToExternalRequest(response);
1451
+ this.log(`[ExternalRequest] Response sent for: ${request.action}`);
1452
+ } catch (error) {
1453
+ this.log(`[ExternalRequest] Handler error:`, error);
1454
+ await this.respondToExternalRequest({
1455
+ requestId: request.requestId,
1456
+ success: false,
1457
+ error: error instanceof Error ? error.message : String(error)
1458
+ });
1459
+ }
1460
+ }
1371
1461
  emitEvent(event) {
1372
1462
  this.log("Event received:", event);
1373
1463
  const listeners = this.eventListeners.get(event.type);
@@ -1528,6 +1618,188 @@ async function verifyExtensionSignature(files, manifest) {
1528
1618
  }
1529
1619
  }
1530
1620
 
1621
+ // src/crypto/vaultKey.ts
1622
+ var PBKDF2_ITERATIONS = 6e5;
1623
+ var KEY_LENGTH = 256;
1624
+ var ALGORITHM = "AES-GCM";
1625
+ async function deriveKeyFromPassword(password, salt) {
1626
+ const encoder = new TextEncoder();
1627
+ const passwordBuffer = encoder.encode(password);
1628
+ const saltBuffer = new Uint8Array(salt);
1629
+ const keyMaterial = await crypto.subtle.importKey(
1630
+ "raw",
1631
+ passwordBuffer,
1632
+ "PBKDF2",
1633
+ false,
1634
+ ["deriveKey"]
1635
+ );
1636
+ return await crypto.subtle.deriveKey(
1637
+ {
1638
+ name: "PBKDF2",
1639
+ salt: saltBuffer,
1640
+ iterations: PBKDF2_ITERATIONS,
1641
+ hash: "SHA-256"
1642
+ },
1643
+ keyMaterial,
1644
+ { name: ALGORITHM, length: KEY_LENGTH },
1645
+ false,
1646
+ // not extractable
1647
+ ["encrypt", "decrypt"]
1648
+ );
1649
+ }
1650
+ function generateVaultKey() {
1651
+ return crypto.getRandomValues(new Uint8Array(32));
1652
+ }
1653
+ async function encryptString(data, derivedKey) {
1654
+ const nonce = crypto.getRandomValues(new Uint8Array(12));
1655
+ const encoder = new TextEncoder();
1656
+ const dataBuffer = encoder.encode(data);
1657
+ const encryptedBuffer = await crypto.subtle.encrypt(
1658
+ {
1659
+ name: ALGORITHM,
1660
+ iv: nonce
1661
+ },
1662
+ derivedKey,
1663
+ dataBuffer
1664
+ );
1665
+ return {
1666
+ encryptedData: arrayBufferToBase64(encryptedBuffer),
1667
+ nonce: arrayBufferToBase64(nonce)
1668
+ };
1669
+ }
1670
+ async function decryptString(encryptedData, nonce, derivedKey) {
1671
+ const encryptedBuffer = base64ToArrayBuffer(encryptedData);
1672
+ const nonceBuffer = base64ToArrayBuffer(nonce);
1673
+ const encryptedDataBuffer = new Uint8Array(encryptedBuffer);
1674
+ const iv = new Uint8Array(nonceBuffer);
1675
+ const decryptedBuffer = await crypto.subtle.decrypt(
1676
+ {
1677
+ name: ALGORITHM,
1678
+ iv
1679
+ },
1680
+ derivedKey,
1681
+ encryptedDataBuffer
1682
+ );
1683
+ const decoder = new TextDecoder();
1684
+ return decoder.decode(decryptedBuffer);
1685
+ }
1686
+ async function encryptVaultKey(vaultKey, password) {
1687
+ const salt = crypto.getRandomValues(new Uint8Array(32));
1688
+ const derivedKey = await deriveKeyFromPassword(password, salt);
1689
+ const nonce = crypto.getRandomValues(new Uint8Array(12));
1690
+ const vaultKeyBuffer = new Uint8Array(vaultKey);
1691
+ const encryptedBuffer = await crypto.subtle.encrypt(
1692
+ {
1693
+ name: ALGORITHM,
1694
+ iv: nonce
1695
+ },
1696
+ derivedKey,
1697
+ vaultKeyBuffer
1698
+ );
1699
+ return {
1700
+ encryptedVaultKey: arrayBufferToBase64(encryptedBuffer),
1701
+ salt: arrayBufferToBase64(salt),
1702
+ vaultKeyNonce: arrayBufferToBase64(nonce)
1703
+ };
1704
+ }
1705
+ async function decryptVaultKey(encryptedVaultKey, salt, vaultKeyNonce, password) {
1706
+ const encryptedBuffer = base64ToArrayBuffer(encryptedVaultKey);
1707
+ const saltBuffer = base64ToArrayBuffer(salt);
1708
+ const nonceBuffer = base64ToArrayBuffer(vaultKeyNonce);
1709
+ const derivedKey = await deriveKeyFromPassword(password, saltBuffer);
1710
+ const encryptedData = new Uint8Array(encryptedBuffer);
1711
+ const iv = new Uint8Array(nonceBuffer);
1712
+ const decryptedBuffer = await crypto.subtle.decrypt(
1713
+ {
1714
+ name: ALGORITHM,
1715
+ iv
1716
+ },
1717
+ derivedKey,
1718
+ encryptedData
1719
+ );
1720
+ return new Uint8Array(decryptedBuffer);
1721
+ }
1722
+ async function decryptVaultName(encryptedVaultName, vaultNameNonce, vaultNameSalt, password) {
1723
+ const saltBuffer = base64ToArrayBuffer(vaultNameSalt);
1724
+ const derivedKey = await deriveKeyFromPassword(password, saltBuffer);
1725
+ return decryptString(encryptedVaultName, vaultNameNonce, derivedKey);
1726
+ }
1727
+ async function encryptCrdtData(data, vaultKey) {
1728
+ const vaultKeyBuffer = new Uint8Array(vaultKey);
1729
+ const cryptoKey = await crypto.subtle.importKey(
1730
+ "raw",
1731
+ vaultKeyBuffer,
1732
+ { name: ALGORITHM },
1733
+ false,
1734
+ ["encrypt"]
1735
+ );
1736
+ const nonce = crypto.getRandomValues(new Uint8Array(12));
1737
+ const encoder = new TextEncoder();
1738
+ const dataBuffer = encoder.encode(JSON.stringify(data));
1739
+ const encryptedBuffer = await crypto.subtle.encrypt(
1740
+ {
1741
+ name: ALGORITHM,
1742
+ iv: nonce
1743
+ },
1744
+ cryptoKey,
1745
+ dataBuffer
1746
+ );
1747
+ return {
1748
+ encryptedData: arrayBufferToBase64(encryptedBuffer),
1749
+ nonce: arrayBufferToBase64(nonce)
1750
+ };
1751
+ }
1752
+ async function decryptCrdtData(encryptedData, nonce, vaultKey) {
1753
+ const vaultKeyBuffer = new Uint8Array(vaultKey);
1754
+ const cryptoKey = await crypto.subtle.importKey(
1755
+ "raw",
1756
+ vaultKeyBuffer,
1757
+ { name: ALGORITHM },
1758
+ false,
1759
+ ["decrypt"]
1760
+ );
1761
+ const encryptedBuffer = base64ToArrayBuffer(encryptedData);
1762
+ const nonceBuffer = base64ToArrayBuffer(nonce);
1763
+ const encryptedDataBuffer = new Uint8Array(encryptedBuffer);
1764
+ const iv = new Uint8Array(nonceBuffer);
1765
+ const decryptedBuffer = await crypto.subtle.decrypt(
1766
+ {
1767
+ name: ALGORITHM,
1768
+ iv
1769
+ },
1770
+ cryptoKey,
1771
+ encryptedDataBuffer
1772
+ );
1773
+ const decoder = new TextDecoder();
1774
+ const jsonString = decoder.decode(decryptedBuffer);
1775
+ return JSON.parse(jsonString);
1776
+ }
1777
+ function arrayBufferToBase64(buffer) {
1778
+ const bytes = buffer instanceof Uint8Array ? buffer : new Uint8Array(buffer);
1779
+ if (typeof Buffer !== "undefined") {
1780
+ return Buffer.from(bytes).toString("base64");
1781
+ }
1782
+ let binary = "";
1783
+ for (let i = 0; i < bytes.length; i++) {
1784
+ const byte = bytes[i];
1785
+ if (byte !== void 0) {
1786
+ binary += String.fromCharCode(byte);
1787
+ }
1788
+ }
1789
+ return btoa(binary);
1790
+ }
1791
+ function base64ToArrayBuffer(base64) {
1792
+ if (typeof Buffer !== "undefined") {
1793
+ return new Uint8Array(Buffer.from(base64, "base64"));
1794
+ }
1795
+ const binary = atob(base64);
1796
+ const bytes = new Uint8Array(binary.length);
1797
+ for (let i = 0; i < binary.length; i++) {
1798
+ bytes[i] = binary.charCodeAt(i);
1799
+ }
1800
+ return bytes;
1801
+ }
1802
+
1531
1803
  // src/index.ts
1532
1804
  function createHaexVaultClient(config = {}) {
1533
1805
  return new HaexVaultClient(config);
@@ -1546,7 +1818,18 @@ exports.PermissionStatus = PermissionStatus;
1546
1818
  exports.PermissionsAPI = PermissionsAPI;
1547
1819
  exports.TABLE_SEPARATOR = TABLE_SEPARATOR;
1548
1820
  exports.WebAPI = WebAPI;
1821
+ exports.arrayBufferToBase64 = arrayBufferToBase64;
1822
+ exports.base64ToArrayBuffer = base64ToArrayBuffer;
1549
1823
  exports.createHaexVaultClient = createHaexVaultClient;
1824
+ exports.decryptCrdtData = decryptCrdtData;
1825
+ exports.decryptString = decryptString;
1826
+ exports.decryptVaultKey = decryptVaultKey;
1827
+ exports.decryptVaultName = decryptVaultName;
1828
+ exports.deriveKeyFromPassword = deriveKeyFromPassword;
1829
+ exports.encryptCrdtData = encryptCrdtData;
1830
+ exports.encryptString = encryptString;
1831
+ exports.encryptVaultKey = encryptVaultKey;
1832
+ exports.generateVaultKey = generateVaultKey;
1550
1833
  exports.getTableName = getTableName;
1551
1834
  exports.hexToBytes = hexToBytes;
1552
1835
  exports.installBaseTag = installBaseTag;