dsh-vault 1.4.0-rc.8 → 1.4.0

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.
package/README-zh.md CHANGED
@@ -61,7 +61,6 @@ dsh-vault 是一个面向 DeepSeek Harness 的安全加密插件:把你在使
61
61
  | `vault_health` | 保险库健康扫描:弱密码/复用凭据、未启用 2FA、不安全的 http:// 站点,以及整体安全评分(0–100) |
62
62
  | `vault_breach_check` | Watchtower 风格泄露扫描:对接 Have I Been Pwned(k-anonymity,仅发送 SHA-1 前缀),附离线常见密码兜底 |
63
63
  | `vault_integrity` | 校验磁盘上的保险库文件可正确解密并与内存中的 store 一致 |
64
- | `vault_integrity` | 校验磁盘上的保险库文件可正确解密并与内存中的 store 一致 |
65
64
  | `vault_merge` | 合并一个条目到另一个;`keepSource: true` 保留源条目 |
66
65
  | `vault_quick_add` | 快速录入(标题 + 一个密钥),支持 tags/notes |
67
66
  | `vault_expiry` | 设置/清除过期(`expiresAt: 0` 移除) |
@@ -73,7 +72,14 @@ dsh-vault 是一个面向 DeepSeek Harness 的安全加密插件:把你在使
73
72
  | `vault_fill` | 按 host/URL/用户名/标题匹配条目并返回其凭据 |
74
73
  | `vault_env` | 把标记 env 的条目(tags 含 `env`)渲染为 `KEY=VALUE` 行 |
75
74
  | `vault_export_bitwarden` / `vault_import_bitwarden` | Bitwarden/Vaultwarden JSON 互通(完整字段映射,支持覆盖) |
76
- | `vault_import_chrome` / `vault_import_keychain` | Chrome Login Data(经 macOS 钥匙串密钥解密)或 macOS 钥匙串导入密码(会话缓存 + 预览,避免授权弹窗轰炸) |
75
+ | `vault_import_bitwarden_encrypted` | 解密 Bitwarden 口令保护 JSON 导出(PBKDF2/Argon2id + HKDF AES-256-CBC + HMAC)并导入,需提供导出口令 |
76
+ | `vault_import_manager_csv` | 密码管理器 CSV 自动识别表头:Bitwarden(login_uri/login_username/…)、1Password 8、Dashlane、NordPass、Keeper、LastPass(fav/grouping/extra);支持 dryRun 预览 |
77
+ | `vault_import_kdbx` | KeePass KDBX:3.1 与 4.x、AES-KDF 或 Argon2(RFC 9106)、AES-256-CBC 或 ChaCha20 载荷、支持 keyfile |
78
+ | `vault_import_1password` / `vault_import_1pif` | 1Password 1PUX(ZIP)与旧版 1PIF 文本导出 |
79
+ | `vault_import_enpass` | Enpass JSON 导出(文件夹→标签、类型化字段、TOTP) |
80
+ | `vault_import_keepass_xml` | KeePass 2.x XML 导出(明文或 ****** 掩码值) |
81
+ | `vault_import_chrome` / `vault_import_keychain` | 从 Chrome Login Data(macOS 钥匙串 / Linux 钥匙环或 peanuts / Windows DPAPI)或 macOS 钥匙串导入密码(会话缓存 + 预览,避免授权弹窗轰炸);所有文件导入均支持 dryRun 预览 |
82
+ | `vault_import_firefox` | Firefox 配置导入(logins.json + key4.db,NSS 3DES / PBES2-AES,支持主密码) |
77
83
  | `vault_search_system` | 在 Chrome / 钥匙串中搜索站点与用户名——绝不暴露密码 |
78
84
  | `vault_copy` | 复制条目(含密钥)到另一个命名保险库 |
79
85
  | `vault_templates` | 内建 + 用户自定义模板(save/list/remove,KeePassXC 风格) |
package/README.md CHANGED
@@ -63,7 +63,6 @@ Each record has a `title`, an optional `kind`, and any combination of fields:
63
63
  | `vault_health` | Vault health scan: weak/reused passwords, missing 2FA, insecure http:// sites, and an overall security score (0–100) |
64
64
  | `vault_breach_check` | Watchtower-style breach scan against Have I Been Pwned (k-anonymity: only the SHA-1 prefix leaves the machine), with an offline common-password fallback |
65
65
  | `vault_integrity` | Verify the on-disk vault file decrypts correctly and matches the in-memory store |
66
- | `vault_integrity` | Verify the on-disk vault file decrypts correctly and matches the in-memory store |
67
66
  | `vault_merge` | Merge one entry into another; `keepSource: true` keeps the source after merging |
68
67
  | `vault_quick_add` | Fast capture (title + one secret) with optional tags/notes |
69
68
  | `vault_expiry` | Set/clear expiry (`expiresAt: 0` removes it) |
@@ -75,7 +74,14 @@ Each record has a `title`, an optional `kind`, and any combination of fields:
75
74
  | `vault_fill` | Find the entry matching a host/URL/username/title and return its credentials |
76
75
  | `vault_env` | Render env-flagged entries (tags contain `env`) as `KEY=VALUE` lines |
77
76
  | `vault_export_bitwarden` / `vault_import_bitwarden` | Bitwarden/Vaultwarden JSON interop (full field mapping, overwrite support) |
78
- | `vault_import_chrome` / `vault_import_keychain` | Import passwords from Chrome's Login Data (decrypted via the macOS keychain key) or the macOS Keychain (session cache + preview, no prompt spam) |
77
+ | `vault_import_bitwarden_encrypted` | Decrypt a Bitwarden password-protected JSON export (PBKDF2/Argon2id + HKDF AES-256-CBC + HMAC) and import it; pass the export passphrase |
78
+ | `vault_import_manager_csv` | Password-manager CSV auto-detected by header: Bitwarden (`login_uri`/`login_username`/…), 1Password 8, Dashlane, NordPass, Keeper, LastPass (`fav`/`grouping`/`extra`); dryRun preview |
79
+ | `vault_import_kdbx` | KeePass KDBX: 3.1 and 4.x, AES-KDF or Argon2 (RFC 9106), AES-256-CBC or ChaCha20 payload, keyfile support |
80
+ | `vault_import_1password` / `vault_import_1pif` | 1Password 1PUX (ZIP) and legacy 1PIF text exports |
81
+ | `vault_import_enpass` | Enpass JSON export (folders → tags, typed fields, TOTP) |
82
+ | `vault_import_keepass_xml` | KeePass 2.x XML export (plaintext or `********` masked values) |
83
+ | `vault_import_chrome` / `vault_import_keychain` | Import passwords from Chrome's Login Data (macOS keychain / Linux keyring or `peanuts` / Windows DPAPI) or the macOS Keychain (session cache + preview, no prompt spam); every file import supports `dryRun` preview |
84
+ | `vault_import_firefox` | Firefox profile import (logins.json + key4.db, NSS 3DES / PBES2-AES, primary-password aware) |
79
85
  | `vault_search_system` | Search Chrome / Keychain for sites & usernames — never exposes passwords |
80
86
  | `vault_copy` | Copy an entry (secrets included) into another named vault |
81
87
  | `vault_templates` | Built-in + user-defined templates (save/list/remove), KeePassXC-style |
package/lib/client.js CHANGED
@@ -17,89 +17,89 @@ window.__ModuleLoader__.load({
17
17
  document.head.appendChild(tag);
18
18
  }
19
19
  var VaultSection_module_css_default = {
20
- "toolbar": "t_j5va_toolbar",
21
- "status": "t_j5va_status",
22
- "genOptRow": "t_j5va_genOptRow",
23
- "editorActions": "t_j5va_editorActions",
24
- "lockedBanner": "t_j5va_lockedBanner",
25
- "badgeWarn": "t_j5va_badgeWarn",
26
- "reportBox": "t_j5va_reportBox",
20
+ "checkField": "t_j5va_checkField",
21
+ "tab": "t_j5va_tab",
27
22
  "detailBox": "t_j5va_detailBox",
28
- "editorBody": "t_j5va_editorBody",
29
- "resultCount": "t_j5va_resultCount",
30
- "tabPane": "t_j5va_tabPane",
31
- "rowActions": "t_j5va_rowActions",
32
- "srOnly": "t_j5va_srOnly",
33
- "highBadge": "t_j5va_highBadge",
34
- "auditIssues": "t_j5va_auditIssues",
35
- "policyBar": "t_j5va_policyBar",
36
- "dupGroup": "t_j5va_dupGroup",
37
- "kindChip": "t_j5va_kindChip",
38
- "addButton": "t_j5va_addButton",
39
- "saveButton": "t_j5va_saveButton",
40
- "row": "t_j5va_row",
23
+ "pwBar": "t_j5va_pwBar",
41
24
  "genHist": "t_j5va_genHist",
42
- "sortButton": "t_j5va_sortButton",
43
- "backupButton": "t_j5va_backupButton",
25
+ "policyBar": "t_j5va_policyBar",
26
+ "retryButton": "t_j5va_retryButton",
44
27
  "genOpts": "t_j5va_genOpts",
45
- "tab": "t_j5va_tab",
46
- "pinStar": "t_j5va_pinStar",
47
- "section": "t_j5va_section",
48
- "rowMain": "t_j5va_rowMain",
49
- "badgeOk": "t_j5va_badgeOk",
50
- "dangerButton": "t_j5va_dangerButton",
28
+ "backupButton": "t_j5va_backupButton",
51
29
  "empty": "t_j5va_empty",
52
- "pwMeter": "t_j5va_pwMeter",
30
+ "field": "t_j5va_field",
31
+ "dupNames": "t_j5va_dupNames",
32
+ "copied": "t_j5va_copied",
33
+ "searchBox": "t_j5va_searchBox",
53
34
  "dueBadge": "t_j5va_dueBadge",
54
- "title": "t_j5va_title",
55
- "emptyHint": "t_j5va_emptyHint",
56
- "error": "t_j5va_error",
57
- "checkField": "t_j5va_checkField",
58
- "modeAuto": "t_j5va_modeAuto",
59
- "tabActive": "t_j5va_tabActive",
60
- "totp": "t_j5va_totp",
61
35
  "lockedTag": "t_j5va_lockedTag",
62
- "pwWeak": "t_j5va_pwWeak",
63
- "list": "t_j5va_list",
64
- "totpRing": "t_j5va_totpRing",
65
- "auditRow": "t_j5va_auditRow",
66
- "retryButton": "t_j5va_retryButton",
67
- "copied": "t_j5va_copied",
36
+ "reportLine": "t_j5va_reportLine",
37
+ "editor": "t_j5va_editor",
38
+ "reportSub": "t_j5va_reportSub",
39
+ "detailItem": "t_j5va_detailItem",
68
40
  "modeReadonly": "t_j5va_modeReadonly",
69
- "emptyBox": "t_j5va_emptyBox",
70
- "searchBox": "t_j5va_searchBox",
71
- "dupMerge": "t_j5va_dupMerge",
72
- "badgeDanger": "t_j5va_badgeDanger",
73
- "footer": "t_j5va_footer",
74
- "kindIcon": "t_j5va_kindIcon",
75
- "intro": "t_j5va_intro",
41
+ "badgeOk": "t_j5va_badgeOk",
42
+ "status": "t_j5va_status",
43
+ "list": "t_j5va_list",
44
+ "reportBox": "t_j5va_reportBox",
45
+ "modeAuto": "t_j5va_modeAuto",
46
+ "rowMain": "t_j5va_rowMain",
47
+ "dangerButton": "t_j5va_dangerButton",
48
+ "sortButton": "t_j5va_sortButton",
49
+ "emptyHint": "t_j5va_emptyHint",
50
+ "title": "t_j5va_title",
51
+ "secretField": "t_j5va_secretField",
52
+ "pinStar": "t_j5va_pinStar",
53
+ "pwFair": "t_j5va_pwFair",
76
54
  "pwStrong": "t_j5va_pwStrong",
77
- "reportSub": "t_j5va_reportSub",
78
- "tabs": "t_j5va_tabs",
55
+ "uriCode": "t_j5va_uriCode",
56
+ "emptyBox": "t_j5va_emptyBox",
57
+ "tabActive": "t_j5va_tabActive",
58
+ "reportTitle": "t_j5va_reportTitle",
59
+ "badgeWarn": "t_j5va_badgeWarn",
60
+ "revealButton": "t_j5va_revealButton",
61
+ "kindChip": "t_j5va_kindChip",
62
+ "row": "t_j5va_row",
63
+ "auditRow": "t_j5va_auditRow",
79
64
  "modeAsk": "t_j5va_modeAsk",
80
- "identity": "t_j5va_identity",
81
- "editor": "t_j5va_editor",
82
- "field": "t_j5va_field",
83
- "trashButton": "t_j5va_trashButton",
65
+ "section": "t_j5va_section",
66
+ "clearButton": "t_j5va_clearButton",
67
+ "toolbar": "t_j5va_toolbar",
68
+ "srOnly": "t_j5va_srOnly",
84
69
  "badge": "t_j5va_badge",
85
- "detailItem": "t_j5va_detailItem",
86
- "pwLabel": "t_j5va_pwLabel",
87
- "healthBar": "t_j5va_healthBar",
88
- "dupNames": "t_j5va_dupNames",
89
- "policyField": "t_j5va_policyField",
90
- "scoreRing": "t_j5va_scoreRing",
91
- "pwFair": "t_j5va_pwFair",
92
70
  "rowExpired": "t_j5va_rowExpired",
93
- "revealButton": "t_j5va_revealButton",
94
- "pwBar": "t_j5va_pwBar",
95
71
  "kindFilter": "t_j5va_kindFilter",
96
- "reportLine": "t_j5va_reportLine",
97
- "deleteButton": "t_j5va_deleteButton",
98
- "secretField": "t_j5va_secretField",
99
72
  "rowDue": "t_j5va_rowDue",
100
- "uriCode": "t_j5va_uriCode",
101
- "clearButton": "t_j5va_clearButton",
102
- "reportTitle": "t_j5va_reportTitle"
73
+ "tabPane": "t_j5va_tabPane",
74
+ "kindIcon": "t_j5va_kindIcon",
75
+ "rowActions": "t_j5va_rowActions",
76
+ "policyField": "t_j5va_policyField",
77
+ "deleteButton": "t_j5va_deleteButton",
78
+ "lockedBanner": "t_j5va_lockedBanner",
79
+ "auditIssues": "t_j5va_auditIssues",
80
+ "intro": "t_j5va_intro",
81
+ "identity": "t_j5va_identity",
82
+ "totpRing": "t_j5va_totpRing",
83
+ "editorBody": "t_j5va_editorBody",
84
+ "footer": "t_j5va_footer",
85
+ "scoreRing": "t_j5va_scoreRing",
86
+ "pwLabel": "t_j5va_pwLabel",
87
+ "badgeDanger": "t_j5va_badgeDanger",
88
+ "tabs": "t_j5va_tabs",
89
+ "dupGroup": "t_j5va_dupGroup",
90
+ "resultCount": "t_j5va_resultCount",
91
+ "saveButton": "t_j5va_saveButton",
92
+ "totp": "t_j5va_totp",
93
+ "dupMerge": "t_j5va_dupMerge",
94
+ "trashButton": "t_j5va_trashButton",
95
+ "highBadge": "t_j5va_highBadge",
96
+ "pwMeter": "t_j5va_pwMeter",
97
+ "genOptRow": "t_j5va_genOptRow",
98
+ "editorActions": "t_j5va_editorActions",
99
+ "pwWeak": "t_j5va_pwWeak",
100
+ "addButton": "t_j5va_addButton",
101
+ "healthBar": "t_j5va_healthBar",
102
+ "error": "t_j5va_error"
103
103
  };
104
104
  //#endregion
105
105
  //#region src/client/VaultSection.tsx
@@ -248,7 +248,7 @@ window.__ModuleLoader__.load({
248
248
  }
249
249
  /** Render the Vault settings section. */
250
250
  function VaultSection(props) {
251
- const { t, config, setAccessMode, setAutoCapture, list, search, get, add, update, remove, trash, rotation, health, duplicates, duplicateGroups, merge, history, stats, backupStatus, backup, recent, restore, undeleteAll, totp, status, switchVault, listVaults, touch, verifyAll, breachCheck, generatePassword, strength, generateUsername, templates, saveTemplate, lock, totpUri, tags, renameTag, generatorHistory, backups, restoreBackup, importChrome, importFirefox, import1password, importManagerCsv, importEnpass, importBitwarden, import1pif, importKeePassXml, keychainImport, searchSystem } = props;
251
+ const { t, config, setAccessMode, setAutoCapture, list, search, get, add, update, remove, trash, rotation, health, duplicates, duplicateGroups, merge, history, stats, backupStatus, backup, recent, restore, undeleteAll, totp, status, switchVault, listVaults, touch, verifyAll, breachCheck, generatePassword, strength, generateUsername, templates, saveTemplate, lock, totpUri, tags, renameTag, generatorHistory, backups, restoreBackup, importChrome, importFirefox, import1password, importManagerCsv, importEnpass, importBitwarden, import1pif, importKeePassXml, importBitwardenEncrypted, keychainImport, searchSystem } = props;
252
252
  const searchId = (0, react.useId)();
253
253
  const [query, setQuery] = (0, react.useState)("");
254
254
  const [state, setState] = (0, react.useState)({ status: "loading" });
@@ -454,6 +454,25 @@ window.__ModuleLoader__.load({
454
454
  setBusy(false);
455
455
  }
456
456
  }
457
+ /** Preview a file import (dry run) — reports counts without writing. */
458
+ async function runImportPreview(run) {
459
+ setBusy(true);
460
+ setMessage(null);
461
+ try {
462
+ const r = await run();
463
+ setMessage(`${t("previewLabel")} ${r.note}`);
464
+ } catch {
465
+ setMessage(t("error"));
466
+ } finally {
467
+ setBusy(false);
468
+ }
469
+ }
470
+ /** Preview a file-based import: prompt for the path, then dry-run. */
471
+ async function runFilePreview(promptKey, run) {
472
+ const path = window.prompt(t(promptKey));
473
+ if (path === null || path.trim() === "") return;
474
+ await runImportPreview(() => run(path.trim()));
475
+ }
457
476
  /** Import a password-manager CSV file (Dashlane/NordPass/Keeper). */
458
477
  async function runImportManagerCsv() {
459
478
  const path = window.prompt(t("importManagerCsvPrompt"));
@@ -499,6 +518,23 @@ window.__ModuleLoader__.load({
499
518
  setBusy(false);
500
519
  }
501
520
  }
521
+ /** Import a Bitwarden password-protected JSON export (asks for the export passphrase). */
522
+ async function runImportBitwardenEncrypted() {
523
+ const path = window.prompt(t("importBitwardenEncryptedPrompt"));
524
+ if (path === null || path.trim() === "") return;
525
+ const password = window.prompt(t("importBitwardenEncryptedPasswordPrompt"));
526
+ if (password === null) return;
527
+ setBusy(true);
528
+ setMessage(null);
529
+ try {
530
+ setMessage((await importBitwardenEncrypted(path.trim(), password, false)).note);
531
+ refresh();
532
+ } catch {
533
+ setMessage(t("error"));
534
+ } finally {
535
+ setBusy(false);
536
+ }
537
+ }
502
538
  /** Import a legacy 1Password 1PIF export. */
503
539
  async function runImport1pif() {
504
540
  const path = window.prompt(t("import1pifPrompt"));
@@ -1417,81 +1453,154 @@ window.__ModuleLoader__.load({
1417
1453
  }),
1418
1454
  /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1419
1455
  className: VaultSection_module_css_default.dupGroup,
1420
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
1421
- className: VaultSection_module_css_default.dupNames,
1422
- children: t("import1passwordDesc")
1423
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
1424
- type: "button",
1425
- className: VaultSection_module_css_default.dupMerge,
1426
- onClick: () => void runImport1password(),
1427
- disabled: busy || readonly || locked,
1428
- children: t("import1password")
1429
- })]
1456
+ children: [
1457
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
1458
+ className: VaultSection_module_css_default.dupNames,
1459
+ children: t("import1passwordDesc")
1460
+ }),
1461
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
1462
+ type: "button",
1463
+ className: VaultSection_module_css_default.dupMerge,
1464
+ onClick: () => void runImport1password(),
1465
+ disabled: busy || readonly || locked,
1466
+ children: t("import1password")
1467
+ }),
1468
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
1469
+ type: "button",
1470
+ className: VaultSection_module_css_default.dupMerge,
1471
+ onClick: () => void runFilePreview("import1passwordPrompt", import1password),
1472
+ disabled: busy || readonly || locked,
1473
+ children: t("preview")
1474
+ })
1475
+ ]
1430
1476
  }),
1431
1477
  /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1432
1478
  className: VaultSection_module_css_default.dupGroup,
1433
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
1434
- className: VaultSection_module_css_default.dupNames,
1435
- children: t("importManagerCsvDesc")
1436
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
1437
- type: "button",
1438
- className: VaultSection_module_css_default.dupMerge,
1439
- onClick: () => void runImportManagerCsv(),
1440
- disabled: busy || readonly || locked,
1441
- children: t("importManagerCsv")
1442
- })]
1479
+ children: [
1480
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
1481
+ className: VaultSection_module_css_default.dupNames,
1482
+ children: t("importManagerCsvDesc")
1483
+ }),
1484
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
1485
+ type: "button",
1486
+ className: VaultSection_module_css_default.dupMerge,
1487
+ onClick: () => void runImportManagerCsv(),
1488
+ disabled: busy || readonly || locked,
1489
+ children: t("importManagerCsv")
1490
+ }),
1491
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
1492
+ type: "button",
1493
+ className: VaultSection_module_css_default.dupMerge,
1494
+ onClick: () => void runFilePreview("importManagerCsvPrompt", importManagerCsv),
1495
+ disabled: busy || readonly || locked,
1496
+ children: t("preview")
1497
+ })
1498
+ ]
1443
1499
  }),
1444
1500
  /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1445
1501
  className: VaultSection_module_css_default.dupGroup,
1446
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
1447
- className: VaultSection_module_css_default.dupNames,
1448
- children: t("importEnpassDesc")
1449
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
1450
- type: "button",
1451
- className: VaultSection_module_css_default.dupMerge,
1452
- onClick: () => void runImportEnpass(),
1453
- disabled: busy || readonly || locked,
1454
- children: t("importEnpass")
1455
- })]
1502
+ children: [
1503
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
1504
+ className: VaultSection_module_css_default.dupNames,
1505
+ children: t("importEnpassDesc")
1506
+ }),
1507
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
1508
+ type: "button",
1509
+ className: VaultSection_module_css_default.dupMerge,
1510
+ onClick: () => void runImportEnpass(),
1511
+ disabled: busy || readonly || locked,
1512
+ children: t("importEnpass")
1513
+ }),
1514
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
1515
+ type: "button",
1516
+ className: VaultSection_module_css_default.dupMerge,
1517
+ onClick: () => void runFilePreview("importEnpassPrompt", importEnpass),
1518
+ disabled: busy || readonly || locked,
1519
+ children: t("preview")
1520
+ })
1521
+ ]
1456
1522
  }),
1457
1523
  /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1458
1524
  className: VaultSection_module_css_default.dupGroup,
1459
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
1460
- className: VaultSection_module_css_default.dupNames,
1461
- children: t("importBitwardenDesc")
1462
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
1463
- type: "button",
1464
- className: VaultSection_module_css_default.dupMerge,
1465
- onClick: () => void runImportBitwarden(),
1466
- disabled: busy || readonly || locked,
1467
- children: t("importBitwarden")
1468
- })]
1525
+ children: [
1526
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
1527
+ className: VaultSection_module_css_default.dupNames,
1528
+ children: t("importBitwardenDesc")
1529
+ }),
1530
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
1531
+ type: "button",
1532
+ className: VaultSection_module_css_default.dupMerge,
1533
+ onClick: () => void runImportBitwarden(),
1534
+ disabled: busy || readonly || locked,
1535
+ children: t("importBitwarden")
1536
+ }),
1537
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
1538
+ type: "button",
1539
+ className: VaultSection_module_css_default.dupMerge,
1540
+ onClick: () => void runFilePreview("importBitwardenPrompt", importBitwarden),
1541
+ disabled: busy || readonly || locked,
1542
+ children: t("preview")
1543
+ })
1544
+ ]
1469
1545
  }),
1470
1546
  /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1471
1547
  className: VaultSection_module_css_default.dupGroup,
1472
1548
  children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
1473
1549
  className: VaultSection_module_css_default.dupNames,
1474
- children: t("import1pifDesc")
1550
+ children: t("importBitwardenEncryptedDesc")
1475
1551
  }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
1476
1552
  type: "button",
1477
1553
  className: VaultSection_module_css_default.dupMerge,
1478
- onClick: () => void runImport1pif(),
1554
+ onClick: () => void runImportBitwardenEncrypted(),
1479
1555
  disabled: busy || readonly || locked,
1480
- children: t("import1pif")
1556
+ children: t("importBitwardenEncrypted")
1481
1557
  })]
1482
1558
  }),
1483
1559
  /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1484
1560
  className: VaultSection_module_css_default.dupGroup,
1485
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
1486
- className: VaultSection_module_css_default.dupNames,
1487
- children: t("importKeePassXmlDesc")
1488
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
1489
- type: "button",
1490
- className: VaultSection_module_css_default.dupMerge,
1491
- onClick: () => void runImportKeePassXml(),
1492
- disabled: busy || readonly || locked,
1493
- children: t("importKeePassXml")
1494
- })]
1561
+ children: [
1562
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
1563
+ className: VaultSection_module_css_default.dupNames,
1564
+ children: t("import1pifDesc")
1565
+ }),
1566
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
1567
+ type: "button",
1568
+ className: VaultSection_module_css_default.dupMerge,
1569
+ onClick: () => void runImport1pif(),
1570
+ disabled: busy || readonly || locked,
1571
+ children: t("import1pif")
1572
+ }),
1573
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
1574
+ type: "button",
1575
+ className: VaultSection_module_css_default.dupMerge,
1576
+ onClick: () => void runFilePreview("import1pifPrompt", import1pif),
1577
+ disabled: busy || readonly || locked,
1578
+ children: t("preview")
1579
+ })
1580
+ ]
1581
+ }),
1582
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1583
+ className: VaultSection_module_css_default.dupGroup,
1584
+ children: [
1585
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
1586
+ className: VaultSection_module_css_default.dupNames,
1587
+ children: t("importKeePassXmlDesc")
1588
+ }),
1589
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
1590
+ type: "button",
1591
+ className: VaultSection_module_css_default.dupMerge,
1592
+ onClick: () => void runImportKeePassXml(),
1593
+ disabled: busy || readonly || locked,
1594
+ children: t("importKeePassXml")
1595
+ }),
1596
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
1597
+ type: "button",
1598
+ className: VaultSection_module_css_default.dupMerge,
1599
+ onClick: () => void runFilePreview("importKeePassXmlPrompt", importKeePassXml),
1600
+ disabled: busy || readonly || locked,
1601
+ children: t("preview")
1602
+ })
1603
+ ]
1495
1604
  })
1496
1605
  ]
1497
1606
  })]
@@ -2578,6 +2687,8 @@ window.__ModuleLoader__.load({
2578
2687
  importKeychain: "Import Keychain",
2579
2688
  importKeychainDesc: "macOS Keychain (generic passwords)",
2580
2689
  keychainPreview: "Preview",
2690
+ preview: "Preview",
2691
+ previewLabel: "Preview —",
2581
2692
  keychainPromptWarn: "Importing from the Keychain may prompt macOS for authorization for each entry. First time: choose \"Always Allow\" to consent once for this process. Continue?",
2582
2693
  systemSearch: "Search system stores",
2583
2694
  sysSearchPlaceholder: "Search Chrome / Keychain…",
@@ -2597,6 +2708,10 @@ window.__ModuleLoader__.load({
2597
2708
  importBitwarden: "Import Bitwarden",
2598
2709
  importBitwardenDesc: "Bitwarden JSON export (.json)",
2599
2710
  importBitwardenPrompt: "Path to the Bitwarden .json export:",
2711
+ importBitwardenEncrypted: "Import Bitwarden (encrypted)",
2712
+ importBitwardenEncryptedDesc: "Bitwarden password-protected JSON export (.json)",
2713
+ importBitwardenEncryptedPrompt: "Path to the encrypted Bitwarden .json export:",
2714
+ importBitwardenEncryptedPasswordPrompt: "Export passphrase (the one chosen when creating the encrypted export):",
2600
2715
  import1pif: "Import 1Password 1PIF",
2601
2716
  import1pifDesc: "Legacy 1Password 1PIF export (.1pif)",
2602
2717
  import1pifPrompt: "Path to the .1pif file:",
@@ -2784,6 +2899,8 @@ window.__ModuleLoader__.load({
2784
2899
  importKeychain: "导入钥匙串",
2785
2900
  importKeychainDesc: "macOS 钥匙串(通用密码)",
2786
2901
  keychainPreview: "预览",
2902
+ preview: "预览",
2903
+ previewLabel: "预览 —",
2787
2904
  keychainPromptWarn: "从钥匙串导入时 macOS 可能为每条凭据弹出授权框。首次请在弹窗中选择“始终允许”一次性授权本进程。是否继续?",
2788
2905
  systemSearch: "搜索系统凭据库",
2789
2906
  sysSearchPlaceholder: "搜索 Chrome / 钥匙串…",
@@ -2803,6 +2920,10 @@ window.__ModuleLoader__.load({
2803
2920
  importBitwarden: "导入 Bitwarden",
2804
2921
  importBitwardenDesc: "Bitwarden JSON 导出(.json)",
2805
2922
  importBitwardenPrompt: "请输入 Bitwarden JSON 导出文件路径:",
2923
+ importBitwardenEncrypted: "导入 Bitwarden(加密)",
2924
+ importBitwardenEncryptedDesc: "Bitwarden 加密 JSON 导出(.json)",
2925
+ importBitwardenEncryptedPrompt: "请输入加密 Bitwarden JSON 导出文件路径:",
2926
+ importBitwardenEncryptedPasswordPrompt: "导出口令(创建加密导出时设置的口令):",
2806
2927
  import1pif: "导入 1Password 1PIF",
2807
2928
  import1pifDesc: "旧版 1Password 1PIF 导出(.1pif)",
2808
2929
  import1pifPrompt: "请输入 .1pif 文件路径:",
@@ -2962,29 +3083,41 @@ window.__ModuleLoader__.load({
2962
3083
  overwrite: overwrite ?? false
2963
3084
  }),
2964
3085
  keychainImport: (options) => invoke("keychainImport", { ...options ?? {} }),
2965
- import1password: (path, overwrite) => invoke("import1password", {
3086
+ import1password: (path, overwrite, dryRun) => invoke("import1password", {
2966
3087
  path,
2967
- overwrite: overwrite ?? false
3088
+ overwrite: overwrite ?? false,
3089
+ dryRun: dryRun ?? false
2968
3090
  }),
2969
- importManagerCsv: (path, overwrite) => invoke("importManagerCsv", {
3091
+ importManagerCsv: (path, overwrite, dryRun) => invoke("importManagerCsv", {
2970
3092
  path,
2971
- overwrite: overwrite ?? false
3093
+ overwrite: overwrite ?? false,
3094
+ dryRun: dryRun ?? false
2972
3095
  }),
2973
- importEnpass: (path, overwrite) => invoke("importEnpass", {
3096
+ importEnpass: (path, overwrite, dryRun) => invoke("importEnpass", {
2974
3097
  path,
2975
- overwrite: overwrite ?? false
3098
+ overwrite: overwrite ?? false,
3099
+ dryRun: dryRun ?? false
2976
3100
  }),
2977
- importBitwarden: (path, overwrite) => invoke("importBitwarden", {
3101
+ importBitwarden: (path, overwrite, dryRun) => invoke("importBitwarden", {
2978
3102
  path,
2979
- overwrite: overwrite ?? false
3103
+ overwrite: overwrite ?? false,
3104
+ dryRun: dryRun ?? false
2980
3105
  }),
2981
- import1pif: (path, overwrite) => invoke("import1pif", {
3106
+ import1pif: (path, overwrite, dryRun) => invoke("import1pif", {
2982
3107
  path,
2983
- overwrite: overwrite ?? false
3108
+ overwrite: overwrite ?? false,
3109
+ dryRun: dryRun ?? false
2984
3110
  }),
2985
- importKeePassXml: (path, overwrite) => invoke("importKeePassXml", {
3111
+ importBitwardenEncrypted: (path, password, overwrite, dryRun) => invoke("importBitwardenEncrypted", {
2986
3112
  path,
2987
- overwrite: overwrite ?? false
3113
+ password,
3114
+ overwrite: overwrite ?? false,
3115
+ dryRun: dryRun ?? false
3116
+ }),
3117
+ importKeePassXml: (path, overwrite, dryRun) => invoke("importKeePassXml", {
3118
+ path,
3119
+ overwrite: overwrite ?? false,
3120
+ dryRun: dryRun ?? false
2988
3121
  }),
2989
3122
  searchSystem: (query, source, limit) => invoke("searchSystem", {
2990
3123
  query,