dsh-vault 1.8.1 → 1.9.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/lib/client.js CHANGED
@@ -17,91 +17,91 @@ window.__ModuleLoader__.load({
17
17
  document.head.appendChild(tag);
18
18
  }
19
19
  var VaultSection_module_css_default = {
20
+ "checkField": "t_j5va_checkField",
21
+ "dupNames": "t_j5va_dupNames",
20
22
  "dupMerge": "t_j5va_dupMerge",
21
- "auditIssues": "t_j5va_auditIssues",
22
- "resultCount": "t_j5va_resultCount",
23
- "identity": "t_j5va_identity",
24
23
  "uriCode": "t_j5va_uriCode",
25
- "rowDue": "t_j5va_rowDue",
26
- "list": "t_j5va_list",
27
- "dangerButton": "t_j5va_dangerButton",
28
- "reportBox": "t_j5va_reportBox",
24
+ "clearButton": "t_j5va_clearButton",
25
+ "genHist": "t_j5va_genHist",
26
+ "tab": "t_j5va_tab",
27
+ "tabActive": "t_j5va_tabActive",
28
+ "pwFair": "t_j5va_pwFair",
29
+ "saveButton": "t_j5va_saveButton",
30
+ "title": "t_j5va_title",
31
+ "policyBar": "t_j5va_policyBar",
29
32
  "editorActions": "t_j5va_editorActions",
30
- "tabPane": "t_j5va_tabPane",
31
- "badgeDanger": "t_j5va_badgeDanger",
32
- "toolbar": "t_j5va_toolbar",
33
- "badgeWarn": "t_j5va_badgeWarn",
33
+ "reportSub": "t_j5va_reportSub",
34
34
  "detailItem": "t_j5va_detailItem",
35
- "footer": "t_j5va_footer",
36
- "section": "t_j5va_section",
37
- "totpRing": "t_j5va_totpRing",
38
- "saveButton": "t_j5va_saveButton",
39
- "pinOff": "t_j5va_pinOff",
40
- "deleteButton": "t_j5va_deleteButton",
41
- "modeAuto": "t_j5va_modeAuto",
42
- "empty": "t_j5va_empty",
43
- "reportLine": "t_j5va_reportLine",
35
+ "sortButton": "t_j5va_sortButton",
36
+ "editorBody": "t_j5va_editorBody",
37
+ "pwLabel": "t_j5va_pwLabel",
44
38
  "searchBox": "t_j5va_searchBox",
45
- "modeReadonly": "t_j5va_modeReadonly",
46
- "reportTitle": "t_j5va_reportTitle",
47
- "status": "t_j5va_status",
48
- "dueBadge": "t_j5va_dueBadge",
49
- "policyField": "t_j5va_policyField",
50
- "field": "t_j5va_field",
39
+ "addButton": "t_j5va_addButton",
40
+ "pwWeak": "t_j5va_pwWeak",
41
+ "tabs": "t_j5va_tabs",
51
42
  "revealButton": "t_j5va_revealButton",
52
- "totp": "t_j5va_totp",
53
- "backupButton": "t_j5va_backupButton",
54
- "pinStar": "t_j5va_pinStar",
43
+ "pwStrong": "t_j5va_pwStrong",
44
+ "rowActions": "t_j5va_rowActions",
45
+ "kindFilter": "t_j5va_kindFilter",
55
46
  "auditRow": "t_j5va_auditRow",
47
+ "resultCount": "t_j5va_resultCount",
48
+ "modeAsk": "t_j5va_modeAsk",
56
49
  "healthBar": "t_j5va_healthBar",
57
- "checkField": "t_j5va_checkField",
58
- "pwFair": "t_j5va_pwFair",
59
- "kindChip": "t_j5va_kindChip",
60
- "copied": "t_j5va_copied",
61
- "genHist": "t_j5va_genHist",
62
- "tabs": "t_j5va_tabs",
63
- "genOptRow": "t_j5va_genOptRow",
64
- "pwMeter": "t_j5va_pwMeter",
65
50
  "row": "t_j5va_row",
66
- "tab": "t_j5va_tab",
67
- "highBadge": "t_j5va_highBadge",
68
- "srOnly": "t_j5va_srOnly",
69
- "lockedBanner": "t_j5va_lockedBanner",
70
- "policyBar": "t_j5va_policyBar",
71
- "reportSub": "t_j5va_reportSub",
72
- "genOpts": "t_j5va_genOpts",
73
- "pwWeak": "t_j5va_pwWeak",
74
- "editorBody": "t_j5va_editorBody",
51
+ "badge": "t_j5va_badge",
52
+ "footer": "t_j5va_footer",
53
+ "list": "t_j5va_list",
54
+ "field": "t_j5va_field",
55
+ "trashButton": "t_j5va_trashButton",
56
+ "detailBox": "t_j5va_detailBox",
57
+ "kindIcon": "t_j5va_kindIcon",
58
+ "policyField": "t_j5va_policyField",
59
+ "emptyHint": "t_j5va_emptyHint",
75
60
  "scoreRing": "t_j5va_scoreRing",
76
- "addButton": "t_j5va_addButton",
61
+ "totp": "t_j5va_totp",
77
62
  "lockedTag": "t_j5va_lockedTag",
78
- "tabActive": "t_j5va_tabActive",
79
- "sortButton": "t_j5va_sortButton",
80
- "emptyHint": "t_j5va_emptyHint",
81
- "title": "t_j5va_title",
82
- "modeAsk": "t_j5va_modeAsk",
83
- "rowActions": "t_j5va_rowActions",
84
- "editor": "t_j5va_editor",
85
- "trashButton": "t_j5va_trashButton",
86
- "secretField": "t_j5va_secretField",
63
+ "emptyBox": "t_j5va_emptyBox",
64
+ "highBadge": "t_j5va_highBadge",
65
+ "lockedBanner": "t_j5va_lockedBanner",
66
+ "modeReadonly": "t_j5va_modeReadonly",
87
67
  "pinOn": "t_j5va_pinOn",
88
- "detailBox": "t_j5va_detailBox",
68
+ "reportBox": "t_j5va_reportBox",
69
+ "srOnly": "t_j5va_srOnly",
70
+ "modeAuto": "t_j5va_modeAuto",
71
+ "badgeOk": "t_j5va_badgeOk",
72
+ "copied": "t_j5va_copied",
73
+ "genOptRow": "t_j5va_genOptRow",
74
+ "rowExpired": "t_j5va_rowExpired",
75
+ "identity": "t_j5va_identity",
76
+ "dangerButton": "t_j5va_dangerButton",
77
+ "rowDue": "t_j5va_rowDue",
89
78
  "error": "t_j5va_error",
90
- "dupNames": "t_j5va_dupNames",
91
79
  "rowMain": "t_j5va_rowMain",
92
- "pwBar": "t_j5va_pwBar",
93
80
  "dupGroup": "t_j5va_dupGroup",
94
- "pwLabel": "t_j5va_pwLabel",
95
- "badge": "t_j5va_badge",
96
- "pwStrong": "t_j5va_pwStrong",
97
- "emptyBox": "t_j5va_emptyBox",
98
- "badgeOk": "t_j5va_badgeOk",
99
- "clearButton": "t_j5va_clearButton",
81
+ "backupButton": "t_j5va_backupButton",
82
+ "pinStar": "t_j5va_pinStar",
83
+ "reportLine": "t_j5va_reportLine",
84
+ "tabPane": "t_j5va_tabPane",
85
+ "retryButton": "t_j5va_retryButton",
86
+ "secretField": "t_j5va_secretField",
87
+ "section": "t_j5va_section",
88
+ "badgeDanger": "t_j5va_badgeDanger",
89
+ "pwMeter": "t_j5va_pwMeter",
100
90
  "intro": "t_j5va_intro",
101
- "rowExpired": "t_j5va_rowExpired",
102
- "kindFilter": "t_j5va_kindFilter",
103
- "kindIcon": "t_j5va_kindIcon",
104
- "retryButton": "t_j5va_retryButton"
91
+ "deleteButton": "t_j5va_deleteButton",
92
+ "empty": "t_j5va_empty",
93
+ "dueBadge": "t_j5va_dueBadge",
94
+ "pinOff": "t_j5va_pinOff",
95
+ "reportTitle": "t_j5va_reportTitle",
96
+ "kindChip": "t_j5va_kindChip",
97
+ "toolbar": "t_j5va_toolbar",
98
+ "badgeWarn": "t_j5va_badgeWarn",
99
+ "totpRing": "t_j5va_totpRing",
100
+ "status": "t_j5va_status",
101
+ "genOpts": "t_j5va_genOpts",
102
+ "auditIssues": "t_j5va_auditIssues",
103
+ "editor": "t_j5va_editor",
104
+ "pwBar": "t_j5va_pwBar"
105
105
  };
106
106
  //#endregion
107
107
  //#region src/client/VaultSection.tsx
@@ -850,6 +850,42 @@ window.__ModuleLoader__.load({
850
850
  setBusy(false);
851
851
  }
852
852
  }
853
+ /** Export the current security report (weak/reused/no-2FA/http/rotation)
854
+ * as a CSV file (1Password Watchtower-style). Client-side only; the report
855
+ * data is already loaded. */
856
+ async function exportReportCsv() {
857
+ if (report === null) return;
858
+ const esc = (v) => {
859
+ const s = String(v ?? "");
860
+ return /[",\n]/.test(s) ? `"${s.replace(/"/g, "\"\"")}"` : s;
861
+ };
862
+ const lines = [`dsh-vault security report,${(/* @__PURE__ */ new Date()).toISOString()},score=${report.score},verdict=${report.verdict}`];
863
+ lines.push("");
864
+ lines.push("weak passwords,title");
865
+ for (const w of report.weak) lines.push(`weak,${esc(w.title ?? w.id ?? "")}`);
866
+ lines.push("");
867
+ lines.push("reused passwords,title");
868
+ for (const r of report.reused) lines.push(`reused,${esc(r.title ?? r.id ?? "")}`);
869
+ lines.push("");
870
+ lines.push("missing 2FA,title");
871
+ for (const n of report.no2fa) lines.push(`no-2fa,${esc(n.title ?? n.id ?? "")}`);
872
+ lines.push("");
873
+ lines.push("http sites,title");
874
+ for (const h of report.httpSites) lines.push(`http,${esc(h.title ?? h.id ?? "")}`);
875
+ lines.push("");
876
+ lines.push("rotation due,title");
877
+ for (const r of report.rotation) lines.push(`rotation,${esc(r.title ?? r.id ?? "")}`);
878
+ const blob = new Blob(["" + lines.join("\n")], { type: "text/csv;charset=utf-8" });
879
+ const url = URL.createObjectURL(blob);
880
+ const a = document.createElement("a");
881
+ a.href = url;
882
+ a.download = `dsh-vault-security-report-${(/* @__PURE__ */ new Date()).toISOString().slice(0, 10)}.csv`;
883
+ document.body.appendChild(a);
884
+ a.click();
885
+ a.remove();
886
+ URL.revokeObjectURL(url);
887
+ setMessage(t("reportExported"));
888
+ }
853
889
  /** Run a Watchtower-style breach scan and show the result. */
854
890
  async function runBreachCheck() {
855
891
  setBusy(true);
@@ -1671,6 +1707,10 @@ window.__ModuleLoader__.load({
1671
1707
  value: "recent",
1672
1708
  children: t("sortRecent")
1673
1709
  }),
1710
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
1711
+ value: "created",
1712
+ children: t("sortCreated")
1713
+ }),
1674
1714
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
1675
1715
  value: "favorite",
1676
1716
  children: t("sortFavorite")
@@ -2806,7 +2846,7 @@ window.__ModuleLoader__.load({
2806
2846
  children: [filteredCount(state.entries, kindFilter, tagFilter) === 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("li", {
2807
2847
  className: VaultSection_module_css_default.empty,
2808
2848
  children: t("noFiltered")
2809
- }), state.entries.filter((entry) => (kindFilter === "" || entry.kind === kindFilter) && (tagFilter === "" || (entry.tags ?? []).includes(tagFilter))).sort((a, b) => sortBy === "alpha" ? a.title.localeCompare(b.title) : sortBy === "recent" ? (b.updatedAt ?? 0) - (a.updatedAt ?? 0) : (a.favorite === true ? 0 : 1) - (b.favorite === true ? 0 : 1) || (b.updatedAt ?? 0) - (a.updatedAt ?? 0) || a.title.localeCompare(b.title)).slice(0, visibleCount).map((entry) => {
2849
+ }), state.entries.filter((entry) => (kindFilter === "" || entry.kind === kindFilter) && (tagFilter === "" || (entry.tags ?? []).includes(tagFilter))).sort((a, b) => sortBy === "alpha" ? a.title.localeCompare(b.title) : sortBy === "recent" ? (b.updatedAt ?? 0) - (a.updatedAt ?? 0) : sortBy === "created" ? (b.createdAt ?? 0) - (a.createdAt ?? 0) : (a.favorite === true ? 0 : 1) - (b.favorite === true ? 0 : 1) || (b.updatedAt ?? 0) - (a.updatedAt ?? 0) || a.title.localeCompare(b.title)).slice(0, visibleCount).map((entry) => {
2810
2850
  const totpInfo = totpMap[entry.id];
2811
2851
  const remaining = totpInfo !== void 0 && totpInfo.until > 0 ? Math.max(0, Math.ceil((totpInfo.until - nowTick) / 1e3)) : void 0;
2812
2852
  const frac = remaining !== void 0 ? remaining / 30 : 0;
@@ -3158,6 +3198,13 @@ window.__ModuleLoader__.load({
3158
3198
  ")"
3159
3199
  ]
3160
3200
  }),
3201
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
3202
+ type: "button",
3203
+ className: VaultSection_module_css_default.backupButton,
3204
+ onClick: () => void exportReportCsv(),
3205
+ disabled: busy || report === null,
3206
+ children: t("exportReport")
3207
+ }),
3161
3208
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
3162
3209
  type: "button",
3163
3210
  className: VaultSection_module_css_default.backupButton,
@@ -3591,6 +3638,8 @@ window.__ModuleLoader__.load({
3591
3638
  auditTitle: "Needs attention",
3592
3639
  auditEdit: "Edit",
3593
3640
  breachCheck: "Check breaches",
3641
+ exportReport: "Export report",
3642
+ reportExported: "Security report exported as CSV.",
3594
3643
  breachTitle: "Breach scan",
3595
3644
  breachPwned: "password appeared in breaches",
3596
3645
  breachWeak: "common/weak password",
@@ -3786,6 +3835,7 @@ window.__ModuleLoader__.load({
3786
3835
  sortFavorite: "Favorites first",
3787
3836
  sortSmart: "Smart",
3788
3837
  sortRecent: "Sort: recent",
3838
+ sortCreated: "Sort: created",
3789
3839
  highSensitivity: "HIGH",
3790
3840
  pinned: "Pinned",
3791
3841
  togglePinHint: "Toggle pinned (shows at top in pinned/smart sort)",
@@ -3910,6 +3960,8 @@ window.__ModuleLoader__.load({
3910
3960
  auditTitle: "需要处理",
3911
3961
  auditEdit: "编辑",
3912
3962
  breachCheck: "泄露检测",
3963
+ exportReport: "导出安全报告",
3964
+ reportExported: "安全报告已导出为 CSV。",
3913
3965
  breachTitle: "泄露扫描",
3914
3966
  breachPwned: "密码曾出现在数据泄露中",
3915
3967
  breachWeak: "常见/弱密码",
@@ -4105,6 +4157,7 @@ window.__ModuleLoader__.load({
4105
4157
  sortFavorite: "置顶优先",
4106
4158
  sortSmart: "智能排序",
4107
4159
  sortRecent: "排序:最近",
4160
+ sortCreated: "排序:创建时间",
4108
4161
  highSensitivity: "高敏",
4109
4162
  pinned: "已置顶",
4110
4163
  togglePinHint: "切换置顶(置顶/智能排序时显示在最前)",