dsh-vault 1.6.1 → 1.7.0-rc.2

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
@@ -122,7 +122,7 @@ dsh-vault 是一个 **bundle**(声明 `dsh.bundle` 的包):安装到 profile 后
122
122
  ### 方式一:从 npm 安装(最省事)
123
123
 
124
124
  ```sh
125
- dsh plugin --profile demo add dsh-vault
125
+ dsh plugin --profile web add dsh-vault
126
126
  ```
127
127
 
128
128
  npm 包自带**预构建的 `lib/` 产物**,无需 allowBuilds、无需本地编译,安装即用。启动前设置主密码:
@@ -134,7 +134,7 @@ export DSH_VAULT_PASSWORD='你的强主密码'
134
134
  ### 方式二:从 GitHub 安装(锁 tag 或 commit)
135
135
 
136
136
  ```sh
137
- dsh plugin --profile demo add github:Ox0400/dsh-vault#v0.1.1
137
+ dsh plugin --profile web add github:Ox0400/dsh-vault#v0.1.1
138
138
  ```
139
139
 
140
140
  git 安装拉取的是**源码**,`prepare` 脚本会在安装时构建 `lib/`。pnpm ≥10 默认阻止 git 依赖执行构建脚本。实测流程:
@@ -162,7 +162,7 @@ git 安装拉取的是**源码**,`prepare` 脚本会在安装时构建 `lib/`。
162
162
  ### 方式三:本地路径安装到 profile
163
163
 
164
164
  ```sh
165
- dsh plugin --profile demo add /绝对/路径/to/dsh-vault
165
+ dsh plugin --profile web add /绝对/路径/to/dsh-vault
166
166
  ```
167
167
 
168
168
  pnpm 将 checkout 链接进 profile;只要 `lib/` 存在(必要时先在 checkout 里执行 `pnpm build`)即被识别为 bundle。
@@ -170,12 +170,12 @@ pnpm 将 checkout 链接进 profile;只要 `lib/` 存在(必要时先在 checkou
170
170
  ### 方式四:本地 tarball 安装
171
171
 
172
172
  ```sh
173
- npm pack && dsh plugin --profile demo add ./dsh-vault-0.1.1.tgz
173
+ npm pack && dsh plugin --profile web add ./dsh-vault-0.1.1.tgz
174
174
  ```
175
175
 
176
176
  tarball 自带预构建 `lib/` 产物,无需构建或 allowBuilds。
177
177
 
178
- `dsh plugin --profile demo remove dsh-vault` 卸载(同时移除依赖与 layer)。
178
+ `dsh plugin --profile web remove dsh-vault` 卸载(同时移除依赖与 layer)。
179
179
 
180
180
  ## 配置
181
181
 
package/README.md CHANGED
@@ -124,7 +124,7 @@ All four install paths below are **verified end-to-end** (install → bundle lay
124
124
  ### Option 1: Install from npm (easiest)
125
125
 
126
126
  ```sh
127
- dsh plugin --profile demo add dsh-vault
127
+ dsh plugin --profile web add dsh-vault
128
128
  ```
129
129
 
130
130
  npm packages ship **prebuilt `lib/` artifacts** — no allowBuilds, no local compilation, install and go. Set the master password before launching:
@@ -136,7 +136,7 @@ export DSH_VAULT_PASSWORD='your strong master password'
136
136
  ### Option 2: Install from GitHub (pin a tag or commit)
137
137
 
138
138
  ```sh
139
- dsh plugin --profile demo add github:Ox0400/dsh-vault#v0.1.1
139
+ dsh plugin --profile web add github:Ox0400/dsh-vault#v0.1.1
140
140
  ```
141
141
 
142
142
  A git install fetches **sources, not built artifacts**, so the `prepare` script builds `lib/` at install time. pnpm ≥10 blocks git dependencies from running build scripts by default. The verified flow:
@@ -164,7 +164,7 @@ A git install fetches **sources, not built artifacts**, so the `prepare` script
164
164
  ### Option 3: Install from a local path
165
165
 
166
166
  ```sh
167
- dsh plugin --profile demo add /absolute/path/to/dsh-vault
167
+ dsh plugin --profile web add /absolute/path/to/dsh-vault
168
168
  ```
169
169
 
170
170
  pnpm links the checkout into the profile; the bundle is recognized as long as `lib/` exists (run `pnpm build` in the checkout first if needed).
@@ -172,12 +172,12 @@ pnpm links the checkout into the profile; the bundle is recognized as long as `l
172
172
  ### Option 4: Install from a tarball
173
173
 
174
174
  ```sh
175
- npm pack && dsh plugin --profile demo add ./dsh-vault-0.1.1.tgz
175
+ npm pack && dsh plugin --profile web add ./dsh-vault-0.1.1.tgz
176
176
  ```
177
177
 
178
178
  The tarball ships prebuilt `lib/` artifacts, so no build step or `allowBuilds` is required.
179
179
 
180
- `dsh plugin --profile demo remove dsh-vault` uninstalls (removes both the dependency and the layer).
180
+ `dsh plugin --profile web remove dsh-vault` uninstalls (removes both the dependency and the layer).
181
181
 
182
182
  ## Configuration
183
183
 
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
- "healthBar": "t_j5va_healthBar",
21
- "highBadge": "t_j5va_highBadge",
20
+ "modeAuto": "t_j5va_modeAuto",
21
+ "genOpts": "t_j5va_genOpts",
22
+ "emptyHint": "t_j5va_emptyHint",
23
+ "auditRow": "t_j5va_auditRow",
24
+ "identity": "t_j5va_identity",
25
+ "rowDue": "t_j5va_rowDue",
26
+ "detailItem": "t_j5va_detailItem",
27
+ "srOnly": "t_j5va_srOnly",
28
+ "status": "t_j5va_status",
29
+ "modeAsk": "t_j5va_modeAsk",
30
+ "editor": "t_j5va_editor",
31
+ "totpRing": "t_j5va_totpRing",
32
+ "reportBox": "t_j5va_reportBox",
33
+ "pwStrong": "t_j5va_pwStrong",
34
+ "detailBox": "t_j5va_detailBox",
35
+ "kindFilter": "t_j5va_kindFilter",
36
+ "row": "t_j5va_row",
37
+ "uriCode": "t_j5va_uriCode",
22
38
  "intro": "t_j5va_intro",
23
39
  "badge": "t_j5va_badge",
40
+ "list": "t_j5va_list",
24
41
  "addButton": "t_j5va_addButton",
25
- "detailBox": "t_j5va_detailBox",
26
- "pwStrong": "t_j5va_pwStrong",
27
- "trashButton": "t_j5va_trashButton",
28
- "reportLine": "t_j5va_reportLine",
29
- "secretField": "t_j5va_secretField",
30
- "revealButton": "t_j5va_revealButton",
31
- "tab": "t_j5va_tab",
42
+ "title": "t_j5va_title",
43
+ "checkField": "t_j5va_checkField",
44
+ "backupButton": "t_j5va_backupButton",
45
+ "dupGroup": "t_j5va_dupGroup",
32
46
  "rowMain": "t_j5va_rowMain",
33
- "dangerButton": "t_j5va_dangerButton",
34
- "kindFilter": "t_j5va_kindFilter",
35
47
  "pinStar": "t_j5va_pinStar",
36
- "row": "t_j5va_row",
37
- "auditRow": "t_j5va_auditRow",
48
+ "badgeDanger": "t_j5va_badgeDanger",
38
49
  "empty": "t_j5va_empty",
39
- "editor": "t_j5va_editor",
40
- "genOpts": "t_j5va_genOpts",
50
+ "tabPane": "t_j5va_tabPane",
51
+ "pwWeak": "t_j5va_pwWeak",
52
+ "searchBox": "t_j5va_searchBox",
53
+ "policyField": "t_j5va_policyField",
54
+ "section": "t_j5va_section",
55
+ "field": "t_j5va_field",
41
56
  "sortButton": "t_j5va_sortButton",
42
- "policyBar": "t_j5va_policyBar",
43
- "dueBadge": "t_j5va_dueBadge",
44
- "editorBody": "t_j5va_editorBody",
45
- "genHist": "t_j5va_genHist",
57
+ "copied": "t_j5va_copied",
58
+ "rowActions": "t_j5va_rowActions",
59
+ "secretField": "t_j5va_secretField",
46
60
  "editorActions": "t_j5va_editorActions",
47
- "kindIcon": "t_j5va_kindIcon",
61
+ "retryButton": "t_j5va_retryButton",
62
+ "dueBadge": "t_j5va_dueBadge",
48
63
  "modeReadonly": "t_j5va_modeReadonly",
49
- "list": "t_j5va_list",
50
- "dupNames": "t_j5va_dupNames",
51
- "field": "t_j5va_field",
52
- "saveButton": "t_j5va_saveButton",
53
- "checkField": "t_j5va_checkField",
54
- "rowExpired": "t_j5va_rowExpired",
55
- "detailItem": "t_j5va_detailItem",
56
- "tabActive": "t_j5va_tabActive",
57
- "emptyHint": "t_j5va_emptyHint",
58
- "srOnly": "t_j5va_srOnly",
59
- "modeAsk": "t_j5va_modeAsk",
60
- "badgeWarn": "t_j5va_badgeWarn",
61
- "pwWeak": "t_j5va_pwWeak",
62
- "uriCode": "t_j5va_uriCode",
63
- "rowDue": "t_j5va_rowDue",
64
+ "dangerButton": "t_j5va_dangerButton",
65
+ "error": "t_j5va_error",
66
+ "tab": "t_j5va_tab",
67
+ "lockedTag": "t_j5va_lockedTag",
68
+ "reportLine": "t_j5va_reportLine",
69
+ "editorBody": "t_j5va_editorBody",
70
+ "reportTitle": "t_j5va_reportTitle",
71
+ "clearButton": "t_j5va_clearButton",
72
+ "reportSub": "t_j5va_reportSub",
73
+ "badgeOk": "t_j5va_badgeOk",
64
74
  "pwMeter": "t_j5va_pwMeter",
65
- "title": "t_j5va_title",
66
- "lockedBanner": "t_j5va_lockedBanner",
67
- "copied": "t_j5va_copied",
75
+ "badgeWarn": "t_j5va_badgeWarn",
76
+ "dupNames": "t_j5va_dupNames",
77
+ "trashButton": "t_j5va_trashButton",
68
78
  "kindChip": "t_j5va_kindChip",
69
- "searchBox": "t_j5va_searchBox",
70
- "dupGroup": "t_j5va_dupGroup",
71
- "tabs": "t_j5va_tabs",
72
- "status": "t_j5va_status",
73
- "auditIssues": "t_j5va_auditIssues",
74
- "resultCount": "t_j5va_resultCount",
75
- "badgeDanger": "t_j5va_badgeDanger",
76
- "reportTitle": "t_j5va_reportTitle",
77
- "pwBar": "t_j5va_pwBar",
78
- "backupButton": "t_j5va_backupButton",
79
- "lockedTag": "t_j5va_lockedTag",
80
- "deleteButton": "t_j5va_deleteButton",
81
- "rowActions": "t_j5va_rowActions",
82
- "totpRing": "t_j5va_totpRing",
79
+ "genHist": "t_j5va_genHist",
80
+ "healthBar": "t_j5va_healthBar",
81
+ "policyBar": "t_j5va_policyBar",
82
+ "genOptRow": "t_j5va_genOptRow",
83
+ "toolbar": "t_j5va_toolbar",
84
+ "pwLabel": "t_j5va_pwLabel",
85
+ "rowExpired": "t_j5va_rowExpired",
86
+ "saveButton": "t_j5va_saveButton",
83
87
  "footer": "t_j5va_footer",
88
+ "pwFair": "t_j5va_pwFair",
89
+ "revealButton": "t_j5va_revealButton",
90
+ "deleteButton": "t_j5va_deleteButton",
91
+ "highBadge": "t_j5va_highBadge",
84
92
  "dupMerge": "t_j5va_dupMerge",
85
- "retryButton": "t_j5va_retryButton",
86
- "pwLabel": "t_j5va_pwLabel",
87
- "toolbar": "t_j5va_toolbar",
93
+ "emptyBox": "t_j5va_emptyBox",
88
94
  "scoreRing": "t_j5va_scoreRing",
89
- "tabPane": "t_j5va_tabPane",
90
- "identity": "t_j5va_identity",
91
- "reportBox": "t_j5va_reportBox",
92
- "reportSub": "t_j5va_reportSub",
93
- "modeAuto": "t_j5va_modeAuto",
95
+ "resultCount": "t_j5va_resultCount",
96
+ "tabs": "t_j5va_tabs",
97
+ "tabActive": "t_j5va_tabActive",
98
+ "auditIssues": "t_j5va_auditIssues",
94
99
  "totp": "t_j5va_totp",
95
- "genOptRow": "t_j5va_genOptRow",
96
- "badgeOk": "t_j5va_badgeOk",
97
- "clearButton": "t_j5va_clearButton",
98
- "error": "t_j5va_error",
99
- "emptyBox": "t_j5va_emptyBox",
100
- "policyField": "t_j5va_policyField",
101
- "pwFair": "t_j5va_pwFair",
102
- "section": "t_j5va_section"
100
+ "lockedBanner": "t_j5va_lockedBanner",
101
+ "kindIcon": "t_j5va_kindIcon",
102
+ "pwBar": "t_j5va_pwBar"
103
103
  };
104
104
  //#endregion
105
105
  //#region src/client/VaultSection.tsx
@@ -284,7 +284,7 @@ window.__ModuleLoader__.load({
284
284
  }
285
285
  /** Render the Vault settings section. */
286
286
  function VaultSection(props) {
287
- 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, deleteBackup, restoreBackup, importChrome, importFirefox, import1password, importManagerCsv, importEnpass, importBitwarden, import1pif, importKeePassXml, importKdbx, importBitwardenEncrypted, keychainImport, searchSystem, sessionOpen, sessionCollect, sessionClose, sessionListOpen, sessionListSaved, sessionSave, sessionExport, sessionGet, sessionPrune, vaultRename, vaultDelete, watchtower, export1pux, exportBitwarden, recoveryCode, verifyRecovery, recoveryStatus, unlock } = props;
287
+ const { t, config, setAccessMode, setAutoCapture, setAutoLock, 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, deleteBackup, restoreBackup, importChrome, importFirefox, import1password, importManagerCsv, importEnpass, importBitwarden, import1pif, importKeePassXml, importKdbx, importBitwardenEncrypted, keychainImport, searchSystem, sessionOpen, sessionCollect, sessionClose, sessionListOpen, sessionListSaved, sessionSave, sessionExport, sessionGet, sessionPrune, vaultRename, vaultDelete, watchtower, export1pux, exportBitwarden, recoveryCode, verifyRecovery, recoveryStatus, unlock } = props;
288
288
  const searchId = (0, react.useId)();
289
289
  const [query, setQuery] = (0, react.useState)("");
290
290
  const [state, setState] = (0, react.useState)({ status: "loading" });
@@ -357,6 +357,15 @@ window.__ModuleLoader__.load({
357
357
  if (clean.length === 0) return t("error");
358
358
  return t("errDetail").replace("{detail}", clean);
359
359
  }
360
+ /** Format an auto-lock timeout (seconds) for display: 90 → "1m 30s". */
361
+ function formatAutoLock(seconds) {
362
+ if (seconds <= 0) return "0";
363
+ const m = Math.floor(seconds / 60);
364
+ const s = seconds % 60;
365
+ if (m === 0) return `${s}s`;
366
+ if (s === 0) return `${m}m`;
367
+ return `${m}m ${s}s`;
368
+ }
360
369
  (0, react.useEffect)(() => {
361
370
  const url = form.url ?? "";
362
371
  if (url.length === 0 || (form.icon ?? "").length > 0) return;
@@ -2542,9 +2551,61 @@ window.__ModuleLoader__.load({
2542
2551
  }
2543
2552
  })]
2544
2553
  }),
2554
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", {
2555
+ className: VaultSection_module_css_default.policyField,
2556
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: t("autoLockLabel") }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("select", {
2557
+ value: policy.autoLockSeconds,
2558
+ disabled: busy,
2559
+ onChange: (event) => {
2560
+ const next = Number(event.target.value);
2561
+ setBusy(true);
2562
+ setMessage(null);
2563
+ setAutoLock(next).then((value) => {
2564
+ setPolicy((previous) => previous ? {
2565
+ ...previous,
2566
+ autoLockSeconds: value.seconds
2567
+ } : previous);
2568
+ setBusy(false);
2569
+ }, (err) => {
2570
+ setMessage(errText(err));
2571
+ setBusy(false);
2572
+ });
2573
+ },
2574
+ children: [
2575
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
2576
+ value: 0,
2577
+ children: t("autoLockNever")
2578
+ }),
2579
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
2580
+ value: 60,
2581
+ children: t("autoLock1m")
2582
+ }),
2583
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
2584
+ value: 300,
2585
+ children: t("autoLock5m")
2586
+ }),
2587
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
2588
+ value: 900,
2589
+ children: t("autoLock15m")
2590
+ }),
2591
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
2592
+ value: 1800,
2593
+ children: t("autoLock30m")
2594
+ }),
2595
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
2596
+ value: 3600,
2597
+ children: t("autoLock1h")
2598
+ })
2599
+ ]
2600
+ })]
2601
+ }),
2545
2602
  /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("p", {
2546
2603
  className: policy.accessMode === "readonly" ? VaultSection_module_css_default.modeReadonly : policy.accessMode === "ask" ? VaultSection_module_css_default.modeAsk : VaultSection_module_css_default.modeAuto,
2547
- children: [policy.accessMode === "readonly" ? t("modeReadonlyHint") : policy.accessMode === "ask" ? t("modeAskHint") : t("modeAutoHint"), policy.autoCapture ? ` · ${t("autoCaptureOn")}` : ` · ${t("autoCaptureOff")}`]
2604
+ children: [
2605
+ policy.accessMode === "readonly" ? t("modeReadonlyHint") : policy.accessMode === "ask" ? t("modeAskHint") : t("modeAutoHint"),
2606
+ policy.autoCapture ? ` · ${t("autoCaptureOn")}` : ` · ${t("autoCaptureOff")}`,
2607
+ policy.autoLockSeconds > 0 ? ` · ${t("autoLockHint")}: ${formatAutoLock(policy.autoLockSeconds)}` : ` · ${t("autoLockNeverHint")}`
2608
+ ]
2548
2609
  })
2549
2610
  ]
2550
2611
  })]
@@ -2821,6 +2882,7 @@ window.__ModuleLoader__.load({
2821
2882
  className: VaultSection_module_css_default.revealButton,
2822
2883
  title: t("copyFieldHint"),
2823
2884
  onClick: () => void copyValue(entry.id, Array.isArray(v) ? v.join(", ") : String(v)),
2885
+ disabled: locked,
2824
2886
  children: "⧉"
2825
2887
  })
2826
2888
  ]
@@ -2840,7 +2902,7 @@ window.__ModuleLoader__.load({
2840
2902
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
2841
2903
  type: "button",
2842
2904
  onClick: () => void copyValue(entry.id, entry.username ?? entry.title),
2843
- disabled: busy,
2905
+ disabled: busy || readonly || locked,
2844
2906
  children: t("copy")
2845
2907
  }),
2846
2908
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
@@ -2858,20 +2920,20 @@ window.__ModuleLoader__.load({
2858
2920
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
2859
2921
  type: "button",
2860
2922
  onClick: () => void showTotp(entry.id),
2861
- disabled: busy,
2923
+ disabled: busy || locked,
2862
2924
  children: t("totp")
2863
2925
  }),
2864
2926
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
2865
2927
  type: "button",
2866
2928
  onClick: () => void showTotpUri(entry.id),
2867
- disabled: busy,
2929
+ disabled: busy || locked,
2868
2930
  title: t("totpUriHint"),
2869
2931
  children: t("totpUri")
2870
2932
  }),
2871
2933
  code !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
2872
2934
  type: "button",
2873
2935
  onClick: () => void copyValue(entry.id, code),
2874
- disabled: busy,
2936
+ disabled: busy || locked,
2875
2937
  children: t("copyCode")
2876
2938
  }),
2877
2939
  entry.url !== void 0 && entry.url !== "" && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
@@ -3710,6 +3772,15 @@ window.__ModuleLoader__.load({
3710
3772
  errInvalidVaultName: "Invalid vault name.",
3711
3773
  errReadonly: "This action is disabled in readonly mode.",
3712
3774
  errDetail: "Something went wrong: {detail}",
3775
+ autoLockLabel: "Auto-lock after",
3776
+ autoLockNever: "Never",
3777
+ autoLock1m: "1 minute",
3778
+ autoLock5m: "5 minutes",
3779
+ autoLock15m: "15 minutes",
3780
+ autoLock30m: "30 minutes",
3781
+ autoLock1h: "1 hour",
3782
+ autoLockHint: "Auto-lock",
3783
+ autoLockNeverHint: "auto-lock off",
3713
3784
  kindLogin: "Login",
3714
3785
  kindSsh: "SSH",
3715
3786
  kindApiKey: "API key",
@@ -4013,6 +4084,15 @@ window.__ModuleLoader__.load({
4013
4084
  errInvalidVaultName: "保险库名称无效。",
4014
4085
  errReadonly: "当前为只读模式,此操作已禁用。",
4015
4086
  errDetail: "操作失败:{detail}",
4087
+ autoLockLabel: "自动锁定",
4088
+ autoLockNever: "永不",
4089
+ autoLock1m: "1 分钟",
4090
+ autoLock5m: "5 分钟",
4091
+ autoLock15m: "15 分钟",
4092
+ autoLock30m: "30 分钟",
4093
+ autoLock1h: "1 小时",
4094
+ autoLockHint: "自动锁定",
4095
+ autoLockNeverHint: "自动锁定已关闭",
4016
4096
  kindLogin: "登录",
4017
4097
  kindSsh: "SSH",
4018
4098
  kindApiKey: "API 密钥",
@@ -4055,6 +4135,7 @@ window.__ModuleLoader__.load({
4055
4135
  config: () => invoke("config"),
4056
4136
  setAccessMode: (mode) => invoke("setAccessMode", { mode }),
4057
4137
  setAutoCapture: (enabled) => invoke("setAutoCapture", { enabled }),
4138
+ setAutoLock: (seconds) => invoke("setAutoLock", { seconds }),
4058
4139
  list: () => invoke("list").then((r) => r.entries),
4059
4140
  search: (query, limit) => invoke("search", {
4060
4141
  query,