dsh-vault 0.9.3 → 0.9.5
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 +113 -51
- package/lib/client.js.map +1 -1
- package/lib/index.js +126 -16
- package/lib/store.js +3 -1
- package/package.json +1 -1
package/lib/client.js
CHANGED
|
@@ -7,7 +7,7 @@ window.__ModuleLoader__.load({
|
|
|
7
7
|
let react = require("react");
|
|
8
8
|
let react_jsx_runtime = require("react/jsx-runtime");
|
|
9
9
|
//#region \0dsh-css:/Users/zhipeng/Desktop/work/dsh test/dsh-vault/src/client/VaultSection.module.css.mjs
|
|
10
|
-
const css = ".t_j5va_section{flex-direction:column;gap:12px;padding:16px 0;display:flex}.t_j5va_intro{opacity:.75;margin:0;font-size:13px}.t_j5va_toolbar{align-items:center;gap:8px;display:flex}.t_j5va_searchBox{flex:1;display:flex}.t_j5va_searchBox input{border:1px solid var(--color-border,#444);color:inherit;background:0 0;border-radius:6px;flex:1;padding:6px 10px;font-size:13px}.t_j5va_addButton,.t_j5va_saveButton{background:var(--color-accent,#4f8cff);color:#fff;cursor:pointer;border:1px solid #0000;border-radius:6px;padding:6px 12px;font-size:13px}.t_j5va_addButton:disabled,.t_j5va_saveButton:disabled,.t_j5va_rowActions button:disabled{opacity:.5;cursor:not-allowed}.t_j5va_list{flex-direction:column;gap:6px;margin:0;padding:0;list-style:none;display:flex}.t_j5va_row{border:1px solid var(--color-border,#333);border-radius:8px;justify-content:space-between;align-items:center;gap:12px;padding:8px 10px;display:flex}.t_j5va_rowMain{flex-direction:column;gap:2px;min-width:0;display:flex}.t_j5va_title{font-size:14px;font-weight:600}.t_j5va_identity{opacity:.7;text-overflow:ellipsis;white-space:nowrap;font-size:12px;overflow:hidden}.t_j5va_totp{font-family:var(--font-mono,monospace);color:var(--color-accent,#4f8cff);font-size:13px}.t_j5va_totpRing{vertical-align:-2px;margin-right:4px;display:inline-block}.t_j5va_rowActions{flex-shrink:0;align-items:center;gap:6px;display:flex}.t_j5va_rowActions button{border:1px solid var(--color-border,#444);color:inherit;cursor:pointer;background:0 0;border-radius:6px;padding:4px 8px;font-size:12px}.t_j5va_deleteButton{color:#e5484d}.t_j5va_copied{color:#30a46c;font-size:12px}.t_j5va_empty,.t_j5va_status,.t_j5va_error{opacity:.8;font-size:13px}.t_j5va_modeReadonly,.t_j5va_modeAsk,.t_j5va_modeAuto{border-radius:999px;width:fit-content;margin:0;padding:4px 10px;font-size:12px;display:inline-block}.t_j5va_modeReadonly{color:#e5484d;border:1px solid #e5484d80}.t_j5va_modeAsk{color:#f5a524;border:1px solid #f5a52480}.t_j5va_modeAuto{color:#30a46c;border:1px solid #30a46c80}.t_j5va_policyBar{flex-direction:column;align-items:flex-start;gap:6px;display:flex}.t_j5va_policyField{align-items:center;gap:8px;font-size:13px;display:flex}.t_j5va_policyField select{border:1px solid var(--color-border,#444);color:inherit;background:0 0;border-radius:6px;padding:4px 8px;font-size:13px}.t_j5va_emptyBox{flex-direction:column;gap:4px;display:flex}.t_j5va_emptyHint{opacity:.65;margin:0;font-size:12px}.t_j5va_error{color:#e5484d}.t_j5va_editor{border:1px solid var(--color-border,#444);border-radius:8px;padding:12px}.t_j5va_editorBody{grid-template-columns:repeat(auto-fill,minmax(220px,1fr));gap:8px 12px;display:grid}.t_j5va_checkField{align-items:center;gap:8px;font-size:13px;display:inline-flex}.t_j5va_field{flex-direction:column;gap:4px;font-size:12px;display:flex}.t_j5va_field input,.t_j5va_field select{border:1px solid var(--color-border,#444);color:inherit;background:0 0;border-radius:6px;padding:5px 8px;font-size:13px}.t_j5va_editorActions{justify-content:flex-end;gap:8px;margin-top:12px;display:flex}.t_j5va_editorActions button{border:1px solid var(--color-border,#444);color:inherit;cursor:pointer;background:0 0;border-radius:6px;padding:6px 12px;font-size:13px}.t_j5va_reportBox{border:1px solid #f5a52466;border-radius:8px;flex-direction:column;gap:2px;padding:8px 10px;font-size:12px;display:flex}.t_j5va_reportTitle{margin:0;font-weight:600}.t_j5va_reportLine{opacity:.8;margin:0}.t_j5va_reportSub{color:var(--dsh-color-text-2,#666);margin:2px 0 0 10px;font-size:12px}.t_j5va_trashButton{border:1px solid var(--color-border,#444);color:inherit;cursor:pointer;background:0 0;border-radius:6px;align-self:flex-start;padding:4px 8px;font-size:12px}.t_j5va_secretField{gap:4px;display:flex}.t_j5va_secretField input{flex:1;min-width:0}.t_j5va_revealButton{border:1px solid var(--color-border,#444);color:inherit;cursor:pointer;background:0 0;border-radius:6px;padding:0 8px;font-size:12px}.t_j5va_kindFilter{border:1px solid var(--color-border,#444);color:inherit;background:0 0;border-radius:6px;padding:6px 8px;font-size:13px}.t_j5va_highBadge{color:#e5484d;vertical-align:middle;background:#e5484d26;border-radius:4px;margin-left:6px;padding:1px 6px;font-size:10px;font-weight:600}.t_j5va_pinStar{color:#f5a524;margin-right:4px}.t_j5va_clearButton{color:inherit;cursor:pointer;opacity:.6;background:0 0;border:none;padding:0 8px;font-size:16px}.t_j5va_field textarea{border:1px solid var(--color-border,#444);color:inherit;resize:vertical;background:0 0;border-radius:6px;padding:5px 8px;font-family:inherit;font-size:13px}.t_j5va_row{transition:background .12s}.t_j5va_row:hover{background:var(--color-hover,#80808014)}.t_j5va_healthBar{flex-wrap:wrap;gap:6px;margin:0 0 10px;display:flex}.t_j5va_badge{border:1px solid var(--dsh-color-border,#ddd);background:var(--dsh-color-surface-2,#f7f7f8);color:var(--dsh-color-text-2,#555);border-radius:999px;padding:4px 10px;font-size:12px;line-height:1}.t_j5va_backupButton{border:1px solid var(--dsh-color-border,#ccc);background:var(--dsh-color-surface-2,#f7f7f8);cursor:pointer;border-radius:999px;padding:4px 10px;font-size:12px;line-height:1}.t_j5va_badgeOk{color:#2e9e5b;border-color:#2e9e5b}.t_j5va_badgeWarn{color:#b57f1a;border-color:#c98a1b}.t_j5va_rowDue{border-left:3px solid #c98a1b}.t_j5va_rowExpired{border-left:3px solid #cf3d3d}.t_j5va_dueBadge{border-radius:999px;margin-left:6px;padding:3px 8px;font-size:11px;font-weight:600;line-height:1}.t_j5va_badgeDanger{color:#c03a3a;border-color:#cf3d3d}.t_j5va_footer{opacity:.6;margin:0;font-size:12px}.t_j5va_kindIcon{margin-right:4px;font-size:12px}.t_j5va_dangerButton{color:#e5484d;cursor:pointer;background:0 0;border:1px solid #e5484d80;border-radius:6px;align-self:flex-start;padding:4px 8px;font-size:12px}.t_j5va_rowMain{cursor:pointer}.t_j5va_detailBox{background:var(--color-hover,#8080800f);border-radius:6px;flex-wrap:wrap;grid-column:1/-1;gap:4px 12px;padding:6px 8px;font-size:12px;display:flex}.t_j5va_detailItem{opacity:.85}.t_j5va_sortButton{border:1px solid var(--color-border,#444);color:inherit;cursor:pointer;background:0 0;border-radius:6px;padding:6px 10px;font-size:13px}.t_j5va_dupGroup{justify-content:space-between;align-items:center;gap:8px;margin:4px 0;display:flex}.t_j5va_dupNames{text-overflow:ellipsis;white-space:nowrap;font-size:12px;overflow:hidden}.t_j5va_dupMerge{border:1px solid var(--dsh-color-border,#ccc);cursor:pointer;border-radius:6px;flex-shrink:0;padding:2px 8px;font-size:12px}";
|
|
10
|
+
const css = ".t_j5va_section{flex-direction:column;gap:12px;padding:16px 0;display:flex}.t_j5va_intro{opacity:.75;margin:0;font-size:13px}.t_j5va_toolbar{align-items:center;gap:8px;display:flex}.t_j5va_searchBox{flex:1;display:flex}.t_j5va_searchBox input{border:1px solid var(--color-border,#444);color:inherit;background:0 0;border-radius:6px;flex:1;padding:6px 10px;font-size:13px}.t_j5va_addButton,.t_j5va_saveButton{background:var(--color-accent,#4f8cff);color:#fff;cursor:pointer;border:1px solid #0000;border-radius:6px;padding:6px 12px;font-size:13px}.t_j5va_addButton:disabled,.t_j5va_saveButton:disabled,.t_j5va_rowActions button:disabled{opacity:.5;cursor:not-allowed}.t_j5va_list{flex-direction:column;gap:6px;margin:0;padding:0;list-style:none;display:flex}.t_j5va_row{border:1px solid var(--color-border,#333);border-radius:8px;justify-content:space-between;align-items:center;gap:12px;padding:8px 10px;display:flex}.t_j5va_rowMain{flex-direction:column;gap:2px;min-width:0;display:flex}.t_j5va_title{font-size:14px;font-weight:600}.t_j5va_identity{opacity:.7;text-overflow:ellipsis;white-space:nowrap;font-size:12px;overflow:hidden}.t_j5va_totp{font-family:var(--font-mono,monospace);color:var(--color-accent,#4f8cff);font-size:13px}.t_j5va_totpRing{vertical-align:-2px;margin-right:4px;display:inline-block}.t_j5va_rowActions{flex-shrink:0;align-items:center;gap:6px;display:flex}.t_j5va_rowActions button{border:1px solid var(--color-border,#444);color:inherit;cursor:pointer;background:0 0;border-radius:6px;padding:4px 8px;font-size:12px}.t_j5va_deleteButton{color:#e5484d}.t_j5va_copied{color:#30a46c;font-size:12px}.t_j5va_empty,.t_j5va_status,.t_j5va_error{opacity:.8;font-size:13px}.t_j5va_lockedBanner{color:#8a5a00;background:#fff4e5;border:1px solid #e0a83a;border-radius:6px;margin:0 0 10px;padding:8px 12px;font-size:13px}.t_j5va_modeReadonly,.t_j5va_modeAsk,.t_j5va_modeAuto{border-radius:999px;width:fit-content;margin:0;padding:4px 10px;font-size:12px;display:inline-block}.t_j5va_modeReadonly{color:#e5484d;border:1px solid #e5484d80}.t_j5va_modeAsk{color:#f5a524;border:1px solid #f5a52480}.t_j5va_modeAuto{color:#30a46c;border:1px solid #30a46c80}.t_j5va_policyBar{flex-direction:column;align-items:flex-start;gap:6px;display:flex}.t_j5va_policyField{align-items:center;gap:8px;font-size:13px;display:flex}.t_j5va_policyField select{border:1px solid var(--color-border,#444);color:inherit;background:0 0;border-radius:6px;padding:4px 8px;font-size:13px}.t_j5va_emptyBox{flex-direction:column;gap:4px;display:flex}.t_j5va_emptyHint{opacity:.65;margin:0;font-size:12px}.t_j5va_error{color:#e5484d}.t_j5va_editor{border:1px solid var(--color-border,#444);border-radius:8px;padding:12px}.t_j5va_editorBody{grid-template-columns:repeat(auto-fill,minmax(220px,1fr));gap:8px 12px;display:grid}.t_j5va_checkField{align-items:center;gap:8px;font-size:13px;display:inline-flex}.t_j5va_field{flex-direction:column;gap:4px;font-size:12px;display:flex}.t_j5va_field input,.t_j5va_field select{border:1px solid var(--color-border,#444);color:inherit;background:0 0;border-radius:6px;padding:5px 8px;font-size:13px}.t_j5va_editorActions{justify-content:flex-end;gap:8px;margin-top:12px;display:flex}.t_j5va_editorActions button{border:1px solid var(--color-border,#444);color:inherit;cursor:pointer;background:0 0;border-radius:6px;padding:6px 12px;font-size:13px}.t_j5va_reportBox{border:1px solid #f5a52466;border-radius:8px;flex-direction:column;gap:2px;padding:8px 10px;font-size:12px;display:flex}.t_j5va_reportTitle{margin:0;font-weight:600}.t_j5va_reportLine{opacity:.8;margin:0}.t_j5va_reportSub{color:var(--dsh-color-text-2,#666);margin:2px 0 0 10px;font-size:12px}.t_j5va_trashButton{border:1px solid var(--color-border,#444);color:inherit;cursor:pointer;background:0 0;border-radius:6px;align-self:flex-start;padding:4px 8px;font-size:12px}.t_j5va_secretField{gap:4px;display:flex}.t_j5va_secretField input{flex:1;min-width:0}.t_j5va_revealButton{border:1px solid var(--color-border,#444);color:inherit;cursor:pointer;background:0 0;border-radius:6px;padding:0 8px;font-size:12px}.t_j5va_kindFilter{border:1px solid var(--color-border,#444);color:inherit;background:0 0;border-radius:6px;padding:6px 8px;font-size:13px}.t_j5va_highBadge{color:#e5484d;vertical-align:middle;background:#e5484d26;border-radius:4px;margin-left:6px;padding:1px 6px;font-size:10px;font-weight:600}.t_j5va_pinStar{color:#f5a524;margin-right:4px}.t_j5va_clearButton{color:inherit;cursor:pointer;opacity:.6;background:0 0;border:none;padding:0 8px;font-size:16px}.t_j5va_field textarea{border:1px solid var(--color-border,#444);color:inherit;resize:vertical;background:0 0;border-radius:6px;padding:5px 8px;font-family:inherit;font-size:13px}.t_j5va_row{transition:background .12s}.t_j5va_row:hover{background:var(--color-hover,#80808014)}.t_j5va_healthBar{flex-wrap:wrap;gap:6px;margin:0 0 10px;display:flex}.t_j5va_badge{border:1px solid var(--dsh-color-border,#ddd);background:var(--dsh-color-surface-2,#f7f7f8);color:var(--dsh-color-text-2,#555);border-radius:999px;padding:4px 10px;font-size:12px;line-height:1}.t_j5va_backupButton{border:1px solid var(--dsh-color-border,#ccc);background:var(--dsh-color-surface-2,#f7f7f8);cursor:pointer;border-radius:999px;padding:4px 10px;font-size:12px;line-height:1}.t_j5va_badgeOk{color:#2e9e5b;border-color:#2e9e5b}.t_j5va_badgeWarn{color:#b57f1a;border-color:#c98a1b}.t_j5va_rowDue{border-left:3px solid #c98a1b}.t_j5va_rowExpired{border-left:3px solid #cf3d3d}.t_j5va_dueBadge{border-radius:999px;margin-left:6px;padding:3px 8px;font-size:11px;font-weight:600;line-height:1}.t_j5va_badgeDanger{color:#c03a3a;border-color:#cf3d3d}.t_j5va_footer{opacity:.6;margin:0;font-size:12px}.t_j5va_kindIcon{margin-right:4px;font-size:12px}.t_j5va_dangerButton{color:#e5484d;cursor:pointer;background:0 0;border:1px solid #e5484d80;border-radius:6px;align-self:flex-start;padding:4px 8px;font-size:12px}.t_j5va_rowMain{cursor:pointer}.t_j5va_detailBox{background:var(--color-hover,#8080800f);border-radius:6px;flex-wrap:wrap;grid-column:1/-1;gap:4px 12px;padding:6px 8px;font-size:12px;display:flex}.t_j5va_detailItem{opacity:.85}.t_j5va_sortButton{border:1px solid var(--color-border,#444);color:inherit;cursor:pointer;background:0 0;border-radius:6px;padding:6px 10px;font-size:13px}.t_j5va_dupGroup{justify-content:space-between;align-items:center;gap:8px;margin:4px 0;display:flex}.t_j5va_dupNames{text-overflow:ellipsis;white-space:nowrap;font-size:12px;overflow:hidden}.t_j5va_dupMerge{border:1px solid var(--dsh-color-border,#ccc);cursor:pointer;border-radius:6px;flex-shrink:0;padding:2px 8px;font-size:12px}";
|
|
11
11
|
const tagId = "dsh-vault/VaultSection.module.css";
|
|
12
12
|
if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=" + JSON.stringify(tagId) + "]") === null) {
|
|
13
13
|
const tag = document.createElement("style");
|
|
@@ -17,66 +17,67 @@ window.__ModuleLoader__.load({
|
|
|
17
17
|
document.head.appendChild(tag);
|
|
18
18
|
}
|
|
19
19
|
var VaultSection_module_css_default = {
|
|
20
|
-
"field": "t_j5va_field",
|
|
21
|
-
"saveButton": "t_j5va_saveButton",
|
|
22
20
|
"clearButton": "t_j5va_clearButton",
|
|
23
|
-
"
|
|
24
|
-
"
|
|
25
|
-
"
|
|
26
|
-
"
|
|
27
|
-
"
|
|
28
|
-
"
|
|
29
|
-
"secretField": "t_j5va_secretField",
|
|
21
|
+
"row": "t_j5va_row",
|
|
22
|
+
"rowMain": "t_j5va_rowMain",
|
|
23
|
+
"totp": "t_j5va_totp",
|
|
24
|
+
"detailBox": "t_j5va_detailBox",
|
|
25
|
+
"saveButton": "t_j5va_saveButton",
|
|
26
|
+
"editor": "t_j5va_editor",
|
|
30
27
|
"modeAuto": "t_j5va_modeAuto",
|
|
31
|
-
"
|
|
32
|
-
"detailItem": "t_j5va_detailItem",
|
|
33
|
-
"sortButton": "t_j5va_sortButton",
|
|
28
|
+
"list": "t_j5va_list",
|
|
34
29
|
"rowActions": "t_j5va_rowActions",
|
|
35
|
-
"
|
|
36
|
-
"
|
|
37
|
-
"deleteButton": "t_j5va_deleteButton",
|
|
30
|
+
"reportTitle": "t_j5va_reportTitle",
|
|
31
|
+
"reportSub": "t_j5va_reportSub",
|
|
38
32
|
"dupNames": "t_j5va_dupNames",
|
|
39
|
-
"
|
|
40
|
-
"dueBadge": "t_j5va_dueBadge",
|
|
33
|
+
"editorBody": "t_j5va_editorBody",
|
|
41
34
|
"trashButton": "t_j5va_trashButton",
|
|
42
|
-
"
|
|
43
|
-
"totp": "t_j5va_totp",
|
|
44
|
-
"searchBox": "t_j5va_searchBox",
|
|
45
|
-
"footer": "t_j5va_footer",
|
|
46
|
-
"dangerButton": "t_j5va_dangerButton",
|
|
47
|
-
"highBadge": "t_j5va_highBadge",
|
|
48
|
-
"copied": "t_j5va_copied",
|
|
35
|
+
"field": "t_j5va_field",
|
|
49
36
|
"rowDue": "t_j5va_rowDue",
|
|
50
|
-
"
|
|
51
|
-
"
|
|
52
|
-
"detailBox": "t_j5va_detailBox",
|
|
53
|
-
"kindFilter": "t_j5va_kindFilter",
|
|
54
|
-
"editorBody": "t_j5va_editorBody",
|
|
55
|
-
"editor": "t_j5va_editor",
|
|
56
|
-
"section": "t_j5va_section",
|
|
57
|
-
"status": "t_j5va_status",
|
|
58
|
-
"modeReadonly": "t_j5va_modeReadonly",
|
|
59
|
-
"editorActions": "t_j5va_editorActions",
|
|
37
|
+
"revealButton": "t_j5va_revealButton",
|
|
38
|
+
"policyField": "t_j5va_policyField",
|
|
60
39
|
"policyBar": "t_j5va_policyBar",
|
|
61
|
-
"
|
|
62
|
-
"title": "t_j5va_title",
|
|
63
|
-
"rowMain": "t_j5va_rowMain",
|
|
64
|
-
"empty": "t_j5va_empty",
|
|
40
|
+
"dangerButton": "t_j5va_dangerButton",
|
|
65
41
|
"backupButton": "t_j5va_backupButton",
|
|
66
|
-
"
|
|
67
|
-
"totpRing": "t_j5va_totpRing",
|
|
68
|
-
"reportLine": "t_j5va_reportLine",
|
|
69
|
-
"revealButton": "t_j5va_revealButton",
|
|
70
|
-
"badgeOk": "t_j5va_badgeOk",
|
|
71
|
-
"list": "t_j5va_list",
|
|
42
|
+
"title": "t_j5va_title",
|
|
72
43
|
"badgeDanger": "t_j5va_badgeDanger",
|
|
73
|
-
"
|
|
74
|
-
"
|
|
75
|
-
"intro": "t_j5va_intro",
|
|
44
|
+
"modeAsk": "t_j5va_modeAsk",
|
|
45
|
+
"reportLine": "t_j5va_reportLine",
|
|
76
46
|
"toolbar": "t_j5va_toolbar",
|
|
47
|
+
"totpRing": "t_j5va_totpRing",
|
|
48
|
+
"dupGroup": "t_j5va_dupGroup",
|
|
49
|
+
"emptyBox": "t_j5va_emptyBox",
|
|
77
50
|
"reportBox": "t_j5va_reportBox",
|
|
51
|
+
"detailItem": "t_j5va_detailItem",
|
|
52
|
+
"searchBox": "t_j5va_searchBox",
|
|
53
|
+
"deleteButton": "t_j5va_deleteButton",
|
|
54
|
+
"pinStar": "t_j5va_pinStar",
|
|
55
|
+
"section": "t_j5va_section",
|
|
56
|
+
"badge": "t_j5va_badge",
|
|
57
|
+
"kindIcon": "t_j5va_kindIcon",
|
|
58
|
+
"intro": "t_j5va_intro",
|
|
59
|
+
"error": "t_j5va_error",
|
|
60
|
+
"emptyHint": "t_j5va_emptyHint",
|
|
61
|
+
"editorActions": "t_j5va_editorActions",
|
|
62
|
+
"lockedBanner": "t_j5va_lockedBanner",
|
|
63
|
+
"copied": "t_j5va_copied",
|
|
64
|
+
"checkField": "t_j5va_checkField",
|
|
65
|
+
"modeReadonly": "t_j5va_modeReadonly",
|
|
66
|
+
"highBadge": "t_j5va_highBadge",
|
|
67
|
+
"empty": "t_j5va_empty",
|
|
68
|
+
"dueBadge": "t_j5va_dueBadge",
|
|
69
|
+
"status": "t_j5va_status",
|
|
70
|
+
"badgeWarn": "t_j5va_badgeWarn",
|
|
71
|
+
"dupMerge": "t_j5va_dupMerge",
|
|
72
|
+
"secretField": "t_j5va_secretField",
|
|
73
|
+
"rowExpired": "t_j5va_rowExpired",
|
|
74
|
+
"healthBar": "t_j5va_healthBar",
|
|
75
|
+
"kindFilter": "t_j5va_kindFilter",
|
|
76
|
+
"sortButton": "t_j5va_sortButton",
|
|
77
|
+
"badgeOk": "t_j5va_badgeOk",
|
|
78
78
|
"identity": "t_j5va_identity",
|
|
79
|
-
"
|
|
79
|
+
"footer": "t_j5va_footer",
|
|
80
|
+
"addButton": "t_j5va_addButton"
|
|
80
81
|
};
|
|
81
82
|
//#endregion
|
|
82
83
|
//#region src/client/VaultSection.tsx
|
|
@@ -195,7 +196,7 @@ window.__ModuleLoader__.load({
|
|
|
195
196
|
}
|
|
196
197
|
/** Render the Vault settings section. */
|
|
197
198
|
function VaultSection(props) {
|
|
198
|
-
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 } = props;
|
|
199
|
+
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 } = props;
|
|
199
200
|
const searchId = (0, react.useId)();
|
|
200
201
|
const [query, setQuery] = (0, react.useState)("");
|
|
201
202
|
const [state, setState] = (0, react.useState)({ status: "loading" });
|
|
@@ -224,7 +225,25 @@ window.__ModuleLoader__.load({
|
|
|
224
225
|
const [recentEntries, setRecentEntries] = (0, react.useState)([]);
|
|
225
226
|
const [dupGroups, setDupGroups] = (0, react.useState)(0);
|
|
226
227
|
const [dupList, setDupList] = (0, react.useState)([]);
|
|
228
|
+
const [locked, setLocked] = (0, react.useState)(false);
|
|
229
|
+
const [vaults, setVaults] = (0, react.useState)([]);
|
|
227
230
|
const readonly = policy?.accessMode === "readonly";
|
|
231
|
+
/** Switch the active vault and reload everything. */
|
|
232
|
+
async function switchVaultTo(name) {
|
|
233
|
+
setBusy(true);
|
|
234
|
+
setMessage(null);
|
|
235
|
+
try {
|
|
236
|
+
await switchVault(name);
|
|
237
|
+
await listVaults().then(setVaults);
|
|
238
|
+
setQuery("");
|
|
239
|
+
refresh();
|
|
240
|
+
status().then((value) => setLocked(value.locked)).catch(() => {});
|
|
241
|
+
} catch {
|
|
242
|
+
setMessage(t("error"));
|
|
243
|
+
} finally {
|
|
244
|
+
setBusy(false);
|
|
245
|
+
}
|
|
246
|
+
}
|
|
228
247
|
/** Merge one duplicate into another (first keeps gaps filled), then refresh. */
|
|
229
248
|
async function mergeEntries(group) {
|
|
230
249
|
if (group.length < 2) return;
|
|
@@ -264,10 +283,18 @@ window.__ModuleLoader__.load({
|
|
|
264
283
|
config().then((value) => {
|
|
265
284
|
if (current) setPolicy(value);
|
|
266
285
|
}, () => {});
|
|
286
|
+
status().then((value) => {
|
|
287
|
+
if (current) setLocked(value.locked);
|
|
288
|
+
}, () => {});
|
|
289
|
+
listVaults().then(setVaults).catch(() => {});
|
|
267
290
|
return () => {
|
|
268
291
|
current = false;
|
|
269
292
|
};
|
|
270
|
-
}, [
|
|
293
|
+
}, [
|
|
294
|
+
config,
|
|
295
|
+
status,
|
|
296
|
+
listVaults
|
|
297
|
+
]);
|
|
271
298
|
const refresh = (0, react.useMemo)(() => async () => {
|
|
272
299
|
setState({ status: "loading" });
|
|
273
300
|
try {
|
|
@@ -275,6 +302,7 @@ window.__ModuleLoader__.load({
|
|
|
275
302
|
status: "ready",
|
|
276
303
|
entries: query.trim().length === 0 ? await list() : await search(query.trim())
|
|
277
304
|
});
|
|
305
|
+
status().then((value) => setLocked(value.locked)).catch(() => {});
|
|
278
306
|
} catch {
|
|
279
307
|
setState({ status: "error" });
|
|
280
308
|
}
|
|
@@ -555,9 +583,24 @@ window.__ModuleLoader__.load({
|
|
|
555
583
|
className: VaultSection_module_css_default.intro,
|
|
556
584
|
children: t("intro")
|
|
557
585
|
}),
|
|
586
|
+
locked && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
587
|
+
role: "alert",
|
|
588
|
+
className: VaultSection_module_css_default.lockedBanner,
|
|
589
|
+
children: t("lockedBanner")
|
|
590
|
+
}),
|
|
558
591
|
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
559
592
|
className: VaultSection_module_css_default.toolbar,
|
|
560
593
|
children: [
|
|
594
|
+
vaults.length > 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("select", {
|
|
595
|
+
className: VaultSection_module_css_default.kindFilter,
|
|
596
|
+
value: vaults.find((v) => v.active)?.name ?? "",
|
|
597
|
+
onChange: (event) => void switchVaultTo(event.target.value),
|
|
598
|
+
"aria-label": t("vaultSelect"),
|
|
599
|
+
children: vaults.map((v) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("option", {
|
|
600
|
+
value: v.name,
|
|
601
|
+
children: [v.name, v.active ? " *" : ""]
|
|
602
|
+
}, v.name))
|
|
603
|
+
}),
|
|
561
604
|
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", {
|
|
562
605
|
className: VaultSection_module_css_default.searchBox,
|
|
563
606
|
children: [
|
|
@@ -1007,6 +1050,13 @@ window.__ModuleLoader__.load({
|
|
|
1007
1050
|
disabled: busy,
|
|
1008
1051
|
children: t("copyCode")
|
|
1009
1052
|
}),
|
|
1053
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
1054
|
+
type: "button",
|
|
1055
|
+
onClick: () => void touch(entry.id).then(() => void refresh()),
|
|
1056
|
+
disabled: busy || readonly,
|
|
1057
|
+
title: t("touchHint"),
|
|
1058
|
+
children: t("touch")
|
|
1059
|
+
}),
|
|
1010
1060
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
1011
1061
|
type: "button",
|
|
1012
1062
|
onClick: () => void startEdit(entry.id),
|
|
@@ -1302,6 +1352,10 @@ window.__ModuleLoader__.load({
|
|
|
1302
1352
|
healthBackup: "backup",
|
|
1303
1353
|
backupNow: "Backup now",
|
|
1304
1354
|
backupDone: "Backup created",
|
|
1355
|
+
lockedBanner: "Vault is locked — unlock it with vault_unlock to read or write entries.",
|
|
1356
|
+
vaultSelect: "Active vault",
|
|
1357
|
+
touch: "Used",
|
|
1358
|
+
touchHint: "Mark as recently used",
|
|
1305
1359
|
healthStrength: "strength",
|
|
1306
1360
|
dueExpired: "EXPIRED",
|
|
1307
1361
|
dueExpiring: "expires in",
|
|
@@ -1404,6 +1458,10 @@ window.__ModuleLoader__.load({
|
|
|
1404
1458
|
healthBackup: "备份",
|
|
1405
1459
|
backupNow: "立即备份",
|
|
1406
1460
|
backupDone: "备份已创建",
|
|
1461
|
+
lockedBanner: "保险库已锁定 —— 请使用 vault_unlock 解锁后再读写条目。",
|
|
1462
|
+
vaultSelect: "当前保险库",
|
|
1463
|
+
touch: "标记已用",
|
|
1464
|
+
touchHint: "标记为最近使用",
|
|
1407
1465
|
healthStrength: "强度",
|
|
1408
1466
|
dueExpired: "已过期",
|
|
1409
1467
|
dueExpiring: "将于",
|
|
@@ -1525,6 +1583,10 @@ window.__ModuleLoader__.load({
|
|
|
1525
1583
|
backup: (maxBackups) => invoke("backup", { maxBackups: maxBackups ?? 10 }),
|
|
1526
1584
|
health: () => invoke("health"),
|
|
1527
1585
|
duplicates: () => invoke("duplicates"),
|
|
1586
|
+
status: () => invoke("status"),
|
|
1587
|
+
switchVault: (name) => invoke("switchVault", { name }),
|
|
1588
|
+
listVaults: () => invoke("listVaults"),
|
|
1589
|
+
touch: (id) => invoke("touch", { id }),
|
|
1528
1590
|
duplicateGroups: () => invoke("duplicateGroups"),
|
|
1529
1591
|
merge: (fromId, toId, keepSource) => invoke("merge", {
|
|
1530
1592
|
fromId,
|
package/lib/client.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"client.js","names":["css"],"sources":["../src/client/VaultSection.tsx","../src/client/locales.ts","../src/client/index.ts"],"sourcesContent":["/**\n * Vault settings section: list, search, add, edit, delete, and copy encrypted\n * credentials. All mutations go through the host VaultGateway remote; secrets\n * are shown only inside the edit form or a copy action, never in the list.\n */\n\nimport { useEffect, useId, useMemo, useState, type ReactNode } from 'react'\nimport type { PropsLocale, PropsRuntime, InjectFace, TranslateNS } from '@deepseek-ai/dsh-client-ui-slots'\nimport type { VaultLocaleKey } from './locales.ts'\nimport css from './VaultSection.module.css'\n\n/** Wire shapes shared with the host gateway (mirror of src/index.ts types). */\nexport interface VaultSummaryWire {\n id: string\n title: string\n sensitivity?: string\n kind?: string\n username?: string\n email?: string\n phone?: string\n host?: string\n port?: string\n url?: string\n tags?: string[]\n icon?: string\n color?: string\n}\n\nexport interface VaultFullWire {\n id: string\n title: string\n kind?: string\n username?: string\n email?: string\n phone?: string\n password?: string\n host?: string\n port?: string\n privateKey?: string\n apiKey?: string\n secret?: string\n accessToken?: string\n refreshToken?: string\n expiresAt?: number\n rotationDays?: number\n sensitivity?: string\n favorite?: boolean\n otpSecret?: string\n url?: string\n notes?: string\n tags?: string[]\n icon?: string\n color?: string\n fields?: Record<string, unknown>\n}\n\n/** Patch shape accepted by vault.add / vault.update. */\nexport type VaultPatch = Partial<Omit<VaultFullWire, 'id'>>\n\n/** Registration-side business face supplied by the plugin entry. */\nexport interface VaultSectionInjected {\n t: TranslateNS<'settings.vault'>\n config: () => Promise<{ accessMode: 'readonly' | 'ask' | 'auto'; autoCapture: boolean }>\n setAccessMode: (mode: 'readonly' | 'ask' | 'auto') => Promise<{ accessMode: 'readonly' | 'ask' | 'auto'; autoCapture: boolean }>\n setAutoCapture: (enabled: boolean) => Promise<{ accessMode: 'readonly' | 'ask' | 'auto'; autoCapture: boolean }>\n list: () => Promise<VaultSummaryWire[]>\n search: (query: string, limit?: number) => Promise<VaultSummaryWire[]>\n get: (id: string) => Promise<{ found: boolean; entry?: VaultFullWire }>\n add: (patch: VaultPatch & { title: string }) => Promise<VaultSummaryWire>\n update: (id: string, patch: VaultPatch) => Promise<{ found: boolean; entry?: VaultSummaryWire }>\n remove: (id: string) => Promise<{ deleted: boolean }>\n trash: () => Promise<VaultSummaryWire[]>\n rotation: () => Promise<unknown[]>\n history: () => Promise<unknown[]>\n stats: () => Promise<Record<string, unknown>>\n recent: () => Promise<unknown[]>\n backupStatus: () => Promise<{ daysSinceBackup: number; backups: number }>\n backup: (maxBackups?: number) => Promise<{ path: string; kept: number; pruned: number }>\n health: () => Promise<{ weak: unknown[]; reused: unknown[]; strength: { weak: number; fair: number; strong: number } }>\n duplicates: () => Promise<{ groups: number }>\n duplicateGroups: () => Promise<Array<Array<{ id: string; title: string }>>>\n merge: (fromId: string, toId: string, keepSource?: boolean) => Promise<{ found: boolean }>\n restore: (id: string) => Promise<{ restored: boolean }>\n undeleteAll: () => Promise<{ restored: number }>\n totp: (id: string) => Promise<{ code: string; label?: string; secondsRemaining: number }>\n}\n\n/** Type-level alias so consumers can reference the wire shapes without values. */\nexport type VaultSectionTypes = {\n entries: VaultSummaryWire[]\n fullEntry: VaultFullWire\n summaryEntry: VaultSummaryWire\n config: { accessMode: 'readonly' | 'ask' | 'auto'; autoCapture: boolean }\n accessModes: Array<'readonly' | 'ask' | 'auto'>\n}\n\n/** Full component props assembled by the Settings slot renderer. */\nexport type VaultSectionProps =\n PropsRuntime<'settings.section'>\n & PropsLocale<'settings.vault'>\n & InjectFace<VaultSectionInjected>\n\n/** The editable form fields we render (subset of the full wire). */\ntype FormFields = {\n title?: string | undefined\n kind?: string | undefined\n username?: string | undefined\n email?: string | undefined\n phone?: string | undefined\n password?: string | undefined\n host?: string | undefined\n port?: string | undefined\n privateKey?: string | undefined\n apiKey?: string | undefined\n secret?: string | undefined\n accessToken?: string | undefined\n refreshToken?: string | undefined\n otpSecret?: string | undefined\n url?: string | undefined\n notes?: string | undefined\n icon?: string | undefined\n color?: string | undefined\n expiresAt?: number | undefined\n rotationDays?: number | undefined\n sensitivity?: string | undefined\n favorite?: boolean | undefined\n}\n\nconst FORM_FIELDS: Array<{ key: keyof FormFields; label: VaultLocaleKey }> = [\n { key: 'title', label: 'fieldTitle' },\n { key: 'kind', label: 'fieldKind' },\n { key: 'username', label: 'fieldUsername' },\n { key: 'email', label: 'fieldEmail' },\n { key: 'phone', label: 'fieldPhone' },\n { key: 'password', label: 'fieldPassword' },\n { key: 'host', label: 'fieldHost' },\n { key: 'port', label: 'fieldPort' },\n { key: 'apiKey', label: 'fieldApiKey' },\n { key: 'secret', label: 'fieldSecret' },\n { key: 'accessToken', label: 'fieldAccessToken' },\n { key: 'refreshToken', label: 'fieldRefreshToken' },\n { key: 'otpSecret', label: 'fieldOtpSecret' },\n { key: 'url', label: 'fieldUrl' },\n { key: 'notes', label: 'fieldNotes' },\n { key: 'expiresAt', label: 'fieldExpiresAt' },\n { key: 'rotationDays', label: 'fieldRotationDays' },\n { key: 'sensitivity', label: 'fieldSensitivity' },\n { key: 'favorite', label: 'fieldFavorite' },\n { key: 'icon', label: 'fieldIcon' },\n { key: 'color', label: 'fieldColor' },\n]\n\nconst KIND_KEYS: Record<string, VaultLocaleKey> = {\n login: 'kindLogin',\n ssh: 'kindSsh',\n 'api-key': 'kindApiKey',\n secret: 'kindSecret',\n oauth: 'kindOauth',\n custom: 'kindCustom',\n}\n\ntype ViewState =\n | { readonly status: 'loading' }\n | { readonly status: 'error' }\n | { readonly status: 'ready'; readonly entries: VaultSummaryWire[] }\n\ntype EditorState =\n | { readonly status: 'closed' }\n | { readonly status: 'creating' }\n | { readonly status: 'editing'; readonly entry: VaultFullWire }\n\nfunction emptyForm(): FormFields {\n return { title: '', kind: 'login', username: '', email: '', phone: '', password: '', host: '', port: '', icon: '', color: '' }\n}\n\n/** Render the Vault settings section. */\nexport function VaultSection(props: VaultSectionProps): ReactNode {\n 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 } = props\n const searchId = useId()\n const [query, setQuery] = useState('')\n const [state, setState] = useState<ViewState>({ status: 'loading' })\n const [editor, setEditor] = useState<EditorState>({ status: 'closed' })\n const [form, setForm] = useState<FormFields>(emptyForm())\n const [busy, setBusy] = useState(false)\n const [message, setMessage] = useState<string | null>(null)\n const [copiedId, setCopiedId] = useState<string | null>(null)\n const [totpMap, setTotpMap] = useState<Record<string, { code: string; until: number }>>({})\n const [nowTick, setNowTick] = useState(Date.now())\n const [tagsDraft, setTagsDraft] = useState('')\n const [fieldsDraft, setFieldsDraft] = useState('')\n const [revealed, setRevealed] = useState<Record<string, boolean>>({})\n const [kindFilter, setKindFilter] = useState('')\n const [tagFilter, setTagFilter] = useState('')\n const [expandedId, setExpandedId] = useState<string | null>(null)\n const [sortBy, setSortBy] = useState<'alpha' | 'recent'>('alpha')\n const [policy, setPolicy] = useState<{ accessMode: 'readonly' | 'ask' | 'auto'; autoCapture: boolean } | null>(null)\n const [showTrash, setShowTrash] = useState(false)\n const [trashEntries, setTrashEntries] = useState<VaultSummaryWire[]>([])\n const [report, setReport] = useState<{ rotation: unknown[]; weak: unknown[]; reused: unknown[]; strength: { weak: number; fair: number; strong: number } | null } | null>(null)\n const [dueMap, setDueMap] = useState<Record<string, { due: string; daysLeft: number }>>({})\n const [recentEvents, setRecentEvents] = useState<Array<Record<string, unknown>>>([])\n const [vaultStats, setVaultStats] = useState<Record<string, unknown> | null>(null)\n const [backupInfo, setBackupInfo] = useState<{ daysSinceBackup: number; backups: number } | null>(null)\n const [recentEntries, setRecentEntries] = useState<Array<Record<string, unknown>>>([])\n const [dupGroups, setDupGroups] = useState<number>(0)\n const [dupList, setDupList] = useState<Array<Array<{ id: string; title: string }>>>([])\n\n const readonly = policy?.accessMode === 'readonly'\n\n /** Merge one duplicate into another (first keeps gaps filled), then refresh. */\n async function mergeEntries(group: Array<{ id: string; title: string }>): Promise<void> {\n if (group.length < 2) return\n setBusy(true)\n setMessage(null)\n try {\n const [first, second] = group\n await merge(second!.id, first!.id, false)\n await duplicateGroups().then(setDupList)\n void refresh()\n } catch {\n setMessage(t('error'))\n } finally {\n setBusy(false)\n }\n }\n\n /** Run an encrypted backup now and refresh the backup-age badge. */\n async function backupNow(): Promise<void> {\n setBusy(true)\n setMessage(null)\n try {\n const result = await backup(10)\n setBackupInfo({ daysSinceBackup: 0, backups: result.kept })\n setMessage(`${t('backupDone')} (${result.kept} kept, ${result.pruned} pruned)`)\n void refresh()\n } catch {\n setMessage(t('error'))\n } finally {\n setBusy(false)\n }\n }\n\n useEffect(() => {\n let current = true\n void config().then(\n value => { if (current) setPolicy(value) },\n () => { /* policy is informational; ignore failures */ },\n )\n return () => { current = false }\n }, [config])\n\n const refresh = useMemo(() => async () => {\n setState({ status: 'loading' })\n try {\n const entries = query.trim().length === 0\n ? await list()\n : await search(query.trim())\n setState({ status: 'ready', entries })\n } catch {\n setState({ status: 'error' })\n }\n }, [list, search, query])\n\n useEffect(() => {\n let current = true\n const timer = window.setTimeout(() => {\n void refresh().then(\n () => { /* state already set inside refresh */ },\n () => { if (current) setState({ status: 'error' }) },\n )\n }, 250)\n return () => { current = false; window.clearTimeout(timer) }\n // refresh is memoized on query (debounced); list/search are stable.\n }, [refresh])\n\n // TOTP countdown: tick every second so the progress ring stays live, and\n // auto-refresh any code whose 30s window just expired.\n useEffect(() => {\n const timer = window.setInterval(() => setNowTick(Date.now()), 1000)\n return () => window.clearInterval(timer)\n }, [])\n\n useEffect(() => {\n for (const [id, info] of Object.entries(totpMap)) {\n if (info.until > 0 && nowTick >= info.until && info.code !== t('error')) {\n void totp(id).then(\n result => setTotpMap(previous => ({\n ...previous,\n [id]: { code: result.code, until: Date.now() + result.secondsRemaining * 1000 },\n })),\n () => { /* keep the last code; next window retries */ },\n )\n }\n }\n }, [nowTick, totpMap, totp])\n\n // Vault health & meta: load once on mount (stats, backup age, rotation,\n // weak/reused scan, recent activity) and refresh on window focus.\n useEffect(() => {\n let current = true\n const load = (): void => {\n void Promise.all([\n stats().catch(() => null),\n backupStatus().catch(() => null),\n rotation().catch(() => []),\n health().catch(() => null),\n recent().catch(() => []),\n duplicates().catch(() => null),\n ]).then(([st, bk, rot, hl, rc, dp]) => {\n if (dp !== null && typeof dp === 'object' && (dp as { groups?: number }).groups !== undefined) {\n setDupGroups((dp as { groups: number }).groups)\n }\n duplicateGroups().then(setDupList).catch(() => {})\n if (!current) return\n if (st !== null) setVaultStats(st as Record<string, unknown>)\n if (bk !== null) setBackupInfo(bk)\n setReport({ rotation: (rot ?? []) as unknown[], weak: ((hl?.weak ?? []) as unknown[]), reused: ((hl?.reused ?? []) as unknown[]), strength: (hl?.strength ?? null) as { weak: number; fair: number; strong: number } | null })\n const due: Record<string, { due: string; daysLeft: number }> = {}\n for (const item of (rot ?? []) as Array<{ id?: string; due?: string; daysLeft?: number }>) {\n if (item.id !== undefined && item.due !== undefined) due[item.id] = { due: item.due, daysLeft: item.daysLeft ?? 0 }\n }\n setDueMap(due)\n setRecentEntries((rc ?? []) as Array<Record<string, unknown>>)\n })\n }\n load()\n const onFocus = (): void => { load() }\n window.addEventListener('focus', onFocus)\n return () => { current = false; window.removeEventListener('focus', onFocus) }\n }, [stats, backupStatus, rotation, health, recent, duplicates, duplicateGroups])\n\n /** Open the editor for a new entry. */\n function startCreate(): void {\n setForm(emptyForm())\n setTagsDraft('')\n setFieldsDraft('')\n setMessage(null)\n setEditor({ status: 'creating' })\n }\n\n /** Open the editor for an existing entry (fetches full secrets). */\n async function startEdit(id: string): Promise<void> {\n setBusy(true)\n setMessage(null)\n try {\n const result = await get(id)\n if (!result.found || result.entry === undefined) {\n setMessage(t('error'))\n return\n }\n const entry = result.entry\n setForm({\n title: entry.title ?? '',\n kind: entry.kind ?? 'login',\n username: entry.username ?? '',\n email: entry.email ?? '',\n phone: entry.phone ?? '',\n password: entry.password ?? '',\n host: entry.host ?? '',\n port: entry.port ?? '',\n privateKey: entry.privateKey ?? '',\n apiKey: entry.apiKey ?? '',\n secret: entry.secret ?? '',\n accessToken: entry.accessToken ?? '',\n refreshToken: entry.refreshToken ?? '',\n otpSecret: entry.otpSecret ?? '',\n url: entry.url ?? '',\n notes: entry.notes ?? '',\n icon: entry.icon ?? '',\n color: entry.color ?? '',\n expiresAt: entry.expiresAt,\n rotationDays: entry.rotationDays,\n sensitivity: entry.sensitivity,\n favorite: entry.favorite ?? false,\n })\n setTagsDraft((entry.tags ?? []).join(', '))\n setFieldsDraft(entry.fields !== undefined ? Object.entries(entry.fields).map(([k, v]) => `${k}=${String(v)}`).join('\\n') : '')\n setEditor({ status: 'editing', entry })\n } catch {\n setMessage(t('error'))\n } finally {\n setBusy(false)\n }\n }\n\n /** Save the current form (create or update). */\n async function save(): Promise<void> {\n if (!(form.title ?? '').trim()) {\n setMessage(t('error'))\n return\n }\n setBusy(true)\n setMessage(null)\n try {\n const tags = tagsDraft.split(',').map(x => x.trim()).filter(x => x.length > 0)\n const fields: Record<string, string> = {}\n for (const line of fieldsDraft.split('\\n')) {\n const trimmed = line.trim()\n if (trimmed.length === 0) continue\n const eq = trimmed.indexOf('=')\n if (eq <= 0) continue\n fields[trimmed.slice(0, eq).trim()] = trimmed.slice(eq + 1).trim()\n }\n const patch: VaultPatch = {\n title: (form.title ?? '').trim(),\n ...(form.kind !== undefined ? { kind: form.kind } : {}),\n ...(form.username !== undefined ? { username: form.username } : {}),\n ...(form.email !== undefined ? { email: form.email } : {}),\n ...(form.phone !== undefined ? { phone: form.phone } : {}),\n ...(form.password !== undefined ? { password: form.password } : {}),\n ...(form.host !== undefined ? { host: form.host } : {}),\n ...(form.port !== undefined ? { port: form.port } : {}),\n ...(form.privateKey !== undefined ? { privateKey: form.privateKey } : {}),\n ...(form.apiKey !== undefined ? { apiKey: form.apiKey } : {}),\n ...(form.secret !== undefined ? { secret: form.secret } : {}),\n ...(form.accessToken !== undefined ? { accessToken: form.accessToken } : {}),\n ...(form.refreshToken !== undefined ? { refreshToken: form.refreshToken } : {}),\n ...(form.otpSecret !== undefined ? { otpSecret: form.otpSecret } : {}),\n ...(form.url !== undefined ? { url: form.url } : {}),\n ...(form.notes !== undefined ? { notes: form.notes } : {}),\n ...(form.icon !== undefined ? { icon: form.icon } : {}),\n ...(form.color !== undefined ? { color: form.color } : {}),\n ...(form.expiresAt !== undefined ? { expiresAt: form.expiresAt } : {}),\n ...(form.rotationDays !== undefined ? { rotationDays: form.rotationDays } : {}),\n ...(form.sensitivity !== undefined ? { sensitivity: form.sensitivity } : {}),\n ...(form.favorite !== undefined ? { favorite: form.favorite } : {}),\n // Always send tags: an empty array clears them, and the host store\n // treats empty string values as \"clear this field\" too.\n tags,\n fields,\n }\n if (editor.status === 'creating') {\n await add(patch as VaultPatch & { title: string })\n } else if (editor.status === 'editing') {\n await update(editor.entry.id, patch)\n }\n setEditor({ status: 'closed' })\n await refresh()\n } catch {\n setMessage(t('error'))\n } finally {\n setBusy(false)\n }\n }\n\n /** Delete an entry after confirmation. */\n async function removeEntry(id: string): Promise<void> {\n if (!window.confirm(t('deleteConfirm'))) return\n setBusy(true)\n try {\n await remove(id)\n await refresh()\n } catch {\n setMessage(t('error'))\n } finally {\n setBusy(false)\n }\n }\n\n /** Copy a field value to the clipboard and flash the row. */\n async function copyValue(id: string, value: string): Promise<void> {\n try {\n await navigator.clipboard.writeText(value)\n } catch {\n // Clipboard may be blocked; fall back to a temporary textarea.\n const textarea = document.createElement('textarea')\n textarea.value = value\n document.body.appendChild(textarea)\n textarea.select()\n document.execCommand('copy')\n textarea.remove()\n }\n setCopiedId(id)\n window.setTimeout(() => setCopiedId(null), 1500)\n }\n\n /** Fetch and display a TOTP code for an entry with an otpSecret. */\n async function showTotp(id: string): Promise<void> {\n setBusy(true)\n try {\n const result = await totp(id)\n setTotpMap(previous => ({ ...previous, [id]: { code: result.code, until: Date.now() + result.secondsRemaining * 1000 } }))\n } catch {\n setTotpMap(previous => ({ ...previous, [id]: { code: t('error'), until: 0 } }))\n } finally {\n setBusy(false)\n }\n }\n\n /** Field-set summary line for one entry (non-secret). */\n function kindIcon(kind?: string): string {\n switch (kind ?? 'login') {\n case 'ssh': return '🖥️'\n case 'api-key': return '🔑'\n case 'oauth': return '🔐'\n case 'secret': return '🤫'\n case 'custom': return '🧩'\n default: return '👤'\n }\n }\n\n function identityLine(entry: VaultSummaryWire): string {\n const parts = [\n entry.kind !== undefined ? t(KIND_KEYS[entry.kind] ?? 'kindCustom') : t('kindLogin'),\n entry.username,\n entry.email,\n entry.phone,\n entry.host !== undefined ? `${entry.host}${entry.port !== undefined ? `:${entry.port}` : ''}` : undefined,\n entry.url,\n ].filter((value): value is string => value !== undefined && value.length > 0)\n return parts.join(' · ')\n }\n\n return (\n <section className={css.section} aria-labelledby=\"vault-heading\">\n <h2 id=\"vault-heading\">{t('heading')}</h2>\n <p className={css.intro}>{t('intro')}</p>\n\n <div className={css.toolbar}>\n <label className={css.searchBox}>\n <span className=\"sr-only\">{t('searchPlaceholder')}</span>\n <input\n id={searchId}\n type=\"search\"\n placeholder={t('searchPlaceholder')}\n value={query}\n onChange={event => setQuery(event.target.value)}\n />\n {query.length > 0 && (\n <button type=\"button\" className={css.clearButton} onClick={() => setQuery('')} aria-label={t('clearSearch')}>×</button>\n )}\n </label>\n <select className={css.kindFilter} value={kindFilter} onChange={e => setKindFilter(e.target.value)} aria-label={t('fieldKind')}>\n <option value=\"\">{t('allKinds')}</option>\n {Object.entries(KIND_KEYS).map(([value, key]) => (\n <option key={value} value={value}>{t(key)}</option>\n ))}\n </select>\n <select className={css.kindFilter} value={tagFilter} onChange={e => setTagFilter(e.target.value)} aria-label={t('fieldTags')}>\n <option value=\"\">{t('allTags')}</option>\n {[...new Set(state.status === 'ready' ? state.entries.flatMap(e => e.tags ?? []) : [])].sort().map(tag => (\n <option key={tag} value={tag}>{tag}</option>\n ))}\n </select>\n <button\n type=\"button\"\n className={css.sortButton}\n onClick={() => setSortBy(sortBy === 'alpha' ? 'recent' : 'alpha')}\n >{sortBy === 'alpha' ? t('sortAlpha') : t('sortRecent')}</button>\n <button type=\"button\" className={css.addButton} onClick={startCreate} disabled={busy || readonly}>\n + {t('add')}\n </button>\n </div>\n\n {policy !== null && (\n <div className={css.policyBar}>\n <label className={css.policyField}>\n <span>{t('modeLabel')}</span>\n <select\n value={policy.accessMode}\n disabled={busy}\n onChange={event => {\n const next = event.target.value as 'readonly' | 'ask' | 'auto'\n setBusy(true)\n setMessage(null)\n void setAccessMode(next).then(\n value => { setPolicy(value); setBusy(false) },\n () => { setMessage(t('error')); setBusy(false) },\n )\n }}\n >\n <option value=\"readonly\">{t('modeReadonly')}</option>\n <option value=\"ask\">{t('modeAsk')}</option>\n <option value=\"auto\">{t('modeAuto')}</option>\n </select>\n </label>\n <label className={css.policyField}>\n <span>{t('autoCaptureLabel')}</span>\n <input\n type=\"checkbox\"\n checked={policy.autoCapture}\n disabled={busy}\n onChange={event => {\n const next = event.target.checked\n setBusy(true)\n setMessage(null)\n void setAutoCapture(next).then(\n value => { setPolicy(value); setBusy(false) },\n () => { setMessage(t('error')); setBusy(false) },\n )\n }}\n />\n </label>\n <p className={policy.accessMode === 'readonly' ? css.modeReadonly : policy.accessMode === 'ask' ? css.modeAsk : css.modeAuto}>\n {policy.accessMode === 'readonly'\n ? t('modeReadonlyHint')\n : policy.accessMode === 'ask'\n ? t('modeAskHint')\n : t('modeAutoHint')}\n {policy.autoCapture ? ` · ${t('autoCaptureOn')}` : ` · ${t('autoCaptureOff')}`}\n </p>\n </div>\n )}\n\n {message !== null && <p role=\"alert\" className={css.error}>{message}</p>}\n\n {state.status === 'loading' && <p className={css.status}>{t('loading')}</p>}\n {state.status === 'error' && <p role=\"alert\" className={css.error}>{t('error')}</p>}\n {state.status === 'ready' && state.entries.length === 0 && (\n <div className={css.emptyBox}>\n <p className={css.empty}>{t('empty')}</p>\n <p className={css.emptyHint}>{readonly ? t('emptyHintReadonly') : t('emptyHint')}</p>\n {!readonly && (\n <button type=\"button\" className={css.addButton} onClick={startCreate}>{t('quickAdd')}</button>\n )}\n </div>\n )}\n\n {recentEntries.length > 0 && (\n <div className={css.reportBox}>\n <p className={css.reportTitle}>{t('recentlyAdded')}</p>\n {recentEntries.map((e, i) => (\n <p key={i} className={css.reportLine}>{String(e.title ?? '')}</p>\n ))}\n </div>\n )}\n\n {recentEvents.length > 0 && (\n <div className={css.reportBox}>\n <p className={css.reportTitle}>{t('recentActivity')}</p>\n {recentEvents.map((ev, i) => (\n <p key={i} className={css.reportLine}>\n {String(ev.action ?? '')} · {String(ev.title ?? ev.id ?? '')}\n </p>\n ))}\n </div>\n )}\n\n {report !== null && (report.rotation.length > 0 || report.weak.length > 0 || report.reused.length > 0) && (\n <div className={css.reportBox}>\n <p className={css.reportTitle}>{t('reportTitle')}</p>\n {report.rotation.length > 0 && (\n <>\n <p className={css.reportLine}>{t('reportRotation')}: {report.rotation.length}</p>\n {(report.rotation as Array<{ title?: string; due?: string; daysLeft?: number }>).slice(0, 8).map((item, i) => (\n <p key={i} className={css.reportSub}>\n · {String(item.title ?? '?')}{item.due === 'expired' ? ` (${t('dueExpired')})` : item.due === 'soon' ? ` (${t('dueExpiring')} ${item.daysLeft ?? 0}d)` : ` (${t('dueNow')})`}\n </p>\n ))}\n </>\n )}\n {report.weak.length > 0 && (\n <>\n <p className={css.reportLine}>{t('reportWeak')}: {report.weak.length}</p>\n {(report.weak as Array<{ title?: string }>).slice(0, 5).map((item, i) => (\n <p key={i} className={css.reportSub}>· {String(item.title ?? '?')}</p>\n ))}\n </>\n )}\n {report.reused.length > 0 && (\n <>\n <p className={css.reportLine}>{t('reportReused')}: {report.reused.length}</p>\n {(report.reused as Array<{ entries?: Array<{ title?: string }> }>).slice(0, 3).map((group, i) => (\n <p key={i} className={css.reportSub}>\n · {(group.entries ?? []).slice(0, 3).map(e => String(e.title ?? '?')).join(' / ')}\n </p>\n ))}\n </>\n )}\n </div>\n )}\n\n {dupList.length > 0 && (\n <div className={css.reportBox}>\n <p className={css.reportTitle}>{t('dupTitle')} ({dupList.length})</p>\n {dupList.slice(0, 5).map((group, gi) => (\n <div key={gi} className={css.dupGroup}>\n <span className={css.dupNames}>{group.map(g => g.title).join(' / ')}</span>\n <button\n type=\"button\"\n className={css.dupMerge}\n onClick={() => void mergeEntries(group)}\n disabled={busy || readonly}\n >{t('dupMerge')}</button>\n </div>\n ))}\n </div>\n )}\n\n {state.status === 'ready' && (state.entries.length > 0 || trashEntries.length > 0) && (\n <button\n type=\"button\"\n className={css.trashButton}\n onClick={() => {\n if (!showTrash) void trash().then(setTrashEntries)\n setShowTrash(!showTrash)\n }}\n >{showTrash ? t('hideTrash') : t('showTrash')}{trashEntries.length > 0 ? ` (${trashEntries.length})` : ''}</button>\n )}\n\n {showTrash && (\n <ul className={css.list}>\n {trashEntries.map(entry => (\n <li key={entry.id} className={css.row}>\n <div className={css.rowMain}>\n <span className={css.title}>{entry.title}</span>\n <span className={css.identity}>{t('trashed')}</span>\n </div>\n <div className={css.rowActions}>\n <button\n type=\"button\"\n onClick={() => { void restore(entry.id).then(() => { void trash().then(setTrashEntries); void refresh() }) }}\n disabled={busy || readonly}\n >{t('restore')}</button>\n </div>\n </li>\n ))}\n {trashEntries.length === 0 && <p className={css.empty}>{t('trashEmpty')}</p>}\n </ul>\n )}\n {showTrash && trashEntries.length > 0 && (\n <>\n <button\n type=\"button\"\n className={css.trashButton}\n onClick={() => {\n setBusy(true)\n void undeleteAll().then(() => {\n void trash().then(setTrashEntries)\n void refresh()\n setBusy(false)\n }, () => setBusy(false))\n }}\n disabled={busy || readonly}\n >{t('restoreAll')}</button>\n <button\n type=\"button\"\n className={css.dangerButton}\n onClick={() => {\n if (!window.confirm(t('clearTrashConfirm'))) return\n setBusy(true)\n void Promise.all(trashEntries.map(e => remove(e.id))).then(() => {\n void trash().then(setTrashEntries)\n void refresh()\n setBusy(false)\n }, () => setBusy(false))\n }}\n disabled={busy || readonly}\n >{t('clearTrash')}</button>\n </>\n )}\n\n {state.status === 'ready' && state.entries.length > 0 && (\n <ul className={css.list}>\n {state.entries.filter(entry => (kindFilter === '' || entry.kind === kindFilter) && (tagFilter === '' || (entry.tags ?? []).includes(tagFilter))).sort((a, b) => sortBy === 'alpha' ? a.title.localeCompare(b.title) : 0).map(entry => {\n const totpInfo = totpMap[entry.id]\n const remaining = totpInfo !== undefined && totpInfo.until > 0 ? Math.max(0, Math.ceil((totpInfo.until - nowTick) / 1000)) : undefined\n const frac = remaining !== undefined ? remaining / 30 : 0\n const code = totpInfo?.code\n return (\n <li key={entry.id} className={`${css.row}${dueMap[entry.id] !== undefined ? ` ${dueMap[entry.id]!.due === 'expired' ? css.rowExpired : css.rowDue}` : ''}`}>\n <div className={css.rowMain} onClick={() => setExpandedId(expandedId === entry.id ? null : entry.id)}>\n <span className={css.title} style={entry.color !== undefined && entry.color !== '' ? { borderLeft: `3px solid ${entry.color}`, paddingLeft: 6 } : undefined}>\n <span className={css.kindIcon}>{entry.icon ?? kindIcon(entry.kind)}</span>\n {(entry as VaultSummaryWire & { favorite?: boolean }).favorite && (\n <span className={css.pinStar} title={t('pinned')}>★</span>\n )}\n {entry.title}\n {(entry as VaultSummaryWire & { sensitivity?: string }).sensitivity === 'high' && (\n <span className={css.highBadge}>{t('highSensitivity')}</span>\n )}\n {dueMap[entry.id] !== undefined && (\n <span className={`${css.dueBadge} ${dueMap[entry.id]!.due === 'expired' ? css.badgeDanger : css.badgeWarn}`}>\n {dueMap[entry.id]!.due === 'expired' ? t('dueExpired') : dueMap[entry.id]!.due === 'soon' ? `${t('dueExpiring')} ${dueMap[entry.id]!.daysLeft}d` : t('dueNow')}\n </span>\n )}\n </span>\n <span className={css.identity}>{identityLine(entry)}</span>\n {code !== undefined && (\n <span className={css.totp}>\n <svg className={css.totpRing} width=\"16\" height=\"16\" viewBox=\"0 0 16 16\" aria-hidden=\"true\">\n <circle cx=\"8\" cy=\"8\" r=\"6.5\" fill=\"none\" stroke=\"var(--dsh-color-border, #ddd)\" strokeWidth=\"2\" />\n <circle\n cx=\"8\" cy=\"8\" r=\"6.5\" fill=\"none\"\n stroke={remaining !== undefined && remaining <= 5 ? '#cf3d3d' : '#2e9e5b'}\n strokeWidth=\"2\" strokeLinecap=\"round\"\n strokeDasharray={`${(frac * 2 * Math.PI * 6.5).toFixed(1)} ${(2 * Math.PI * 6.5).toFixed(1)}`}\n transform=\"rotate(-90 8 8)\"\n />\n </svg>\n {code}{remaining !== undefined ? ` (${remaining}s)` : ''}\n </span>\n )}\n </div>\n {expandedId === entry.id && (\n <div className={css.detailBox}>\n {Object.entries(entry).filter(([k]) => !['id', 'title'].includes(k) && entry[k as keyof VaultSummaryWire] !== undefined).map(([k, v]) => (\n <span key={k} className={css.detailItem}>\n <strong>{k}</strong>: {Array.isArray(v) ? v.join(', ') : String(v)}\n </span>\n ))}\n </div>\n )}\n <div className={css.rowActions}>\n {copiedId === entry.id && <span className={css.copied}>{t('copied')}</span>}\n <button\n type=\"button\"\n onClick={() => void copyValue(entry.id, entry.username ?? entry.title)}\n disabled={busy}\n >{t('copy')}</button>\n <button\n type=\"button\"\n onClick={() => {\n setBusy(true)\n void get(entry.id).then(r => {\n if (r.found && r.entry?.password) void copyValue(entry.id, r.entry.password)\n setBusy(false)\n }, () => setBusy(false))\n }}\n disabled={busy || readonly}\n >{t('copyPassword')}</button>\n <button type=\"button\" onClick={() => void showTotp(entry.id)} disabled={busy}>{t('totp')}</button>\n {code !== undefined && (\n <button type=\"button\" onClick={() => void copyValue(entry.id, code)} disabled={busy}>{t('copyCode')}</button>\n )}\n <button type=\"button\" onClick={() => void startEdit(entry.id)} disabled={busy || readonly}>{t('edit')}</button>\n <button\n type=\"button\"\n className={css.deleteButton}\n onClick={() => void removeEntry(entry.id)}\n disabled={busy || readonly}\n >{t('delete')}</button>\n </div>\n </li>\n )\n })}\n </ul>\n )}\n\n {state.status === 'ready' && (\n <div className={css.healthBar}>\n {vaultStats !== null && typeof vaultStats.total === 'number' && (\n <span className={css.badge}>{t('entryCount')}: {String(vaultStats.total)}</span>\n )}\n {vaultStats !== null && typeof vaultStats.withTotp === 'number' && (\n <span className={css.badge}>TOTP: {String(vaultStats.withTotp)}</span>\n )}\n {vaultStats !== null && typeof vaultStats.highSensitivity === 'number' && (\n <span className={css.badge}>{t('highSensitivity')}: {String(vaultStats.highSensitivity)}</span>\n )}\n {report !== null && report.strength !== null && (\n <span className={`${css.badge} ${report.strength.weak > 0 ? css.badgeDanger : css.badgeOk}`}>\n {t('healthStrength')}: {report.strength.weak}W/{report.strength.fair}F/{report.strength.strong}S\n </span>\n )}\n {report !== null && report.rotation.length > 0 && (\n <span className={`${css.badge} ${css.badgeWarn}`}>{t('reportRotation')}: {report.rotation.length}</span>\n )}\n {report !== null && report.weak.length > 0 && (\n <span className={`${css.badge} ${css.badgeDanger}`}>{t('reportWeak')}: {report.weak.length}</span>\n )}\n {report !== null && report.reused.length > 0 && (\n <span className={`${css.badge} ${css.badgeDanger}`}>{t('reportReused')}: {report.reused.length}</span>\n )}\n {dupGroups > 0 && (\n <span className={`${css.badge} ${css.badgeWarn}`}>{t('dupGroups')}: {dupGroups}</span>\n )}\n {report !== null && report.rotation.length === 0 && report.weak.length === 0 && report.reused.length === 0 && (\n <span className={`${css.badge} ${css.badgeOk}`}>{t('healthOk')}</span>\n )}\n {backupInfo !== null && backupInfo.daysSinceBackup >= 0 && (\n <span className={`${css.badge} ${backupInfo.daysSinceBackup > 14 ? css.badgeDanger : backupInfo.daysSinceBackup > 7 ? css.badgeWarn : ''}`}>\n {t('healthBackup')}: {backupInfo.daysSinceBackup}d\n </span>\n )}\n <button type=\"button\" className={css.backupButton} onClick={() => void backupNow()} disabled={busy}>\n {t('backupNow')}\n </button>\n </div>\n )}\n {state.status === 'ready' && (\n <p className={css.footer}>\n {t('entryCount')}: {state.entries.length}\n {vaultStats !== null && typeof vaultStats.withTotp === 'number' && ` · TOTP: ${String(vaultStats.withTotp)}`}\n {vaultStats !== null && typeof vaultStats.highSensitivity === 'number' && ` · ${t('highSensitivity')}: ${String(vaultStats.highSensitivity)}`}\n {backupInfo !== null && backupInfo.daysSinceBackup >= 0 && ` · backup: ${backupInfo.daysSinceBackup}d ago`}\n {vaultStats !== null && typeof vaultStats.byTag === 'object' && vaultStats.byTag !== null\n && Object.keys(vaultStats.byTag as Record<string, unknown>).length > 0\n && ` · tags: ${Object.entries(vaultStats.byTag as Record<string, unknown>).map(([k, v]) => `${k}(${String(v)})`).join(' ')}`}\n </p>\n )}\n\n {editor.status !== 'closed' && (\n <div className={css.editor} role=\"dialog\" aria-label={editor.status === 'creating' ? t('add') : t('edit')}>\n <div className={css.editorBody}>\n {FORM_FIELDS.map(field => (\n <label key={field.key} className={css.field}>\n <span>{t(field.label)}</span>\n {field.key === 'kind' ? (\n <select\n value={form.kind ?? 'login'}\n onChange={event => setForm(previous => ({ ...previous, kind: event.target.value }))}\n >\n {Object.entries(KIND_KEYS).map(([value, key]) => (\n <option key={value} value={value}>{t(key)}</option>\n ))}\n </select>\n ) : field.key === 'title' ? (\n <input\n value={form.title ?? ''}\n onChange={event => setForm(previous => ({ ...previous, title: event.target.value }))}\n />\n ) : field.key === 'password' || field.key === 'otpSecret' || field.key === 'apiKey'\n || field.key === 'secret' || field.key === 'accessToken' || field.key === 'refreshToken'\n || field.key === 'privateKey' ? (\n <span className={css.secretField}>\n <input\n type={revealed[field.key] ? 'text' : 'password'}\n value={(form[field.key] as string | undefined) ?? ''}\n onChange={event => setForm(previous => ({ ...previous, [field.key]: event.target.value }))}\n />\n <button\n type=\"button\"\n className={css.revealButton}\n onClick={() => setRevealed(previous => ({ ...previous, [field.key]: !previous[field.key] }))}\n >{revealed[field.key] ? t('hide') : t('show')}</button>\n </span>\n ) : field.key === 'expiresAt' ? (\n <input\n type=\"datetime-local\"\n value={form.expiresAt !== undefined ? new Date(form.expiresAt).toISOString().slice(0, 16) : ''}\n onChange={event => {\n const raw = event.target.value\n const epoch = raw.length > 0 ? Date.parse(raw) : NaN\n setForm(previous => ({ ...previous, expiresAt: Number.isNaN(epoch) ? undefined : epoch }))\n }}\n />\n ) : field.key === 'rotationDays' ? (\n <input\n type=\"number\"\n min={0}\n max={3650}\n placeholder={t('rotationClearHint')}\n value={form.rotationDays ?? ''}\n onChange={event => {\n const raw = event.target.value\n setForm(previous => ({ ...previous, rotationDays: raw.length > 0 ? Number(raw) : undefined }))\n }}\n />\n ) : field.key === 'sensitivity' ? (\n <select\n value={form.sensitivity ?? 'normal'}\n onChange={event => setForm(previous => ({ ...previous, sensitivity: event.target.value === 'high' ? 'high' : 'normal' }))}\n >\n <option value=\"normal\">{t('sensitivityNormal')}</option>\n <option value=\"high\">{t('sensitivityHigh')}</option>\n </select>\n ) : field.key === 'favorite' ? (\n <label className={css.checkField}>\n <input\n type=\"checkbox\"\n checked={form.favorite ?? false}\n onChange={event => setForm(previous => ({ ...previous, favorite: event.target.checked }))}\n />\n {t('favoriteHint')}\n </label>\n ) : (\n <input\n type=\"text\"\n value={(form[field.key] as string | undefined) ?? ''}\n onChange={event => setForm(previous => ({ ...previous, [field.key]: event.target.value }))}\n />\n )}\n </label>\n ))}\n <label className={css.field}>\n <span>{t('fieldTags')}</span>\n <input\n value={tagsDraft}\n onChange={event => setTagsDraft(event.target.value)}\n placeholder=\"dev, prod\"\n />\n </label>\n <label className={css.field}>\n <span>{t('fieldCustom')}</span>\n <textarea\n value={fieldsDraft}\n onChange={event => setFieldsDraft(event.target.value)}\n rows={3}\n placeholder=\"region=us-east-1 team=infra\"\n />\n </label>\n </div>\n <div className={css.editorActions}>\n <button type=\"button\" onClick={() => setEditor({ status: 'closed' })} disabled={busy}>{t('cancel')}</button>\n <button type=\"button\" className={css.saveButton} onClick={() => void save()} disabled={busy}>{t('save')}</button>\n </div>\n </div>\n )}\n </section>\n )\n}\n","/** Copy dictionaries for the Vault settings section. */\n\n/** English strings (the key-set source of truth for this pair). */\nexport const en = {\n nav: 'Vault',\n heading: 'Vault',\n intro: 'Encrypted credentials stored on this machine.',\n searchPlaceholder: 'Search title, username, email, host…',\n loading: 'Loading…',\n empty: 'No credentials yet. Add one to get started.',\n emptyHint: 'Tip: you can ask the assistant to save an API key or token you share in chat — with auto-capture on it offers to store it for you. Bulk importing? Ask for vault_import_csv with a CSV file path.',\n emptyHintReadonly: 'The vault is in readonly mode — credentials can be read but not added here. Switch accessMode to \"readwrite\" to enable writes.',\n modeLabel: 'Access mode',\n autoCaptureLabel: 'Auto-capture credentials from chat',\n modeReadonly: 'Read-only',\n modeAsk: 'Ask before writing',\n modeAuto: 'Automatic read-write',\n modeReadonlyHint: 'Read-only — mutations disabled',\n modeAskHint: 'Prompt before writing — every add/update/delete asks you',\n modeAutoHint: 'Automatic read-write — no per-call prompt',\n autoCaptureOn: 'auto-capture on',\n autoCaptureOff: 'auto-capture off',\n clearSearch: 'Clear search',\n entryCount: 'Entries',\n reportTitle: 'Health & rotation',\n recentActivity: 'Recent activity',\n recentlyAdded: 'Recently added',\n reportRotation: 'expired / due for rotation',\n reportWeak: 'weak passwords',\n reportReused: 'credentials reused across entries',\n dupGroups: 'duplicate groups',\n dupTitle: 'Duplicate entries',\n dupMerge: 'Merge',\n healthOk: 'vault healthy',\n healthBackup: 'backup',\n backupNow: 'Backup now',\n backupDone: 'Backup created',\n healthStrength: 'strength',\n dueExpired: 'EXPIRED',\n dueExpiring: 'expires in',\n dueNow: 'rotation due',\n showTrash: 'Trash',\n hideTrash: 'Hide trash',\n trashed: 'in trash',\n trashEmpty: 'Trash is empty',\n restore: 'Restore',\n clearTrash: 'Empty trash',\n restoreAll: 'Restore all',\n clearTrashConfirm: 'Permanently delete ALL trashed entries? This cannot be undone.',\n show: 'Show',\n hide: 'Hide',\n allKinds: 'All kinds',\n allTags: 'All tags',\n sortAlpha: 'Sort: A–Z',\n sortRecent: 'Sort: recent',\n highSensitivity: 'HIGH',\n pinned: 'Pinned',\n add: 'Add credential',\n quickAdd: 'Quick add',\n cancel: 'Cancel',\n save: 'Save',\n edit: 'Edit',\n delete: 'Delete',\n deleteConfirm: 'Delete this entry? This cannot be undone.',\n copy: 'Copy',\n copyPassword: 'Copy password',\n copyCode: 'Copy code',\n copied: 'Copied',\n totp: 'Code',\n fieldTitle: 'Title',\n fieldKind: 'Kind',\n fieldUsername: 'Username',\n fieldEmail: 'Email',\n fieldPhone: 'Phone',\n fieldPassword: 'Password',\n fieldHost: 'Host',\n fieldPort: 'Port',\n fieldApiKey: 'API key',\n fieldSecret: 'Secret',\n fieldAccessToken: 'Access token',\n fieldRefreshToken: 'Refresh token',\n fieldOtpSecret: 'OTP secret',\n fieldUrl: 'URL',\n fieldNotes: 'Notes',\n fieldTags: 'Tags',\n fieldIcon: 'Icon (emoji)',\n fieldExpiresAt: 'Expires at',\n fieldRotationDays: 'Rotation (days, 0 = never)',\n fieldSensitivity: 'Sensitivity',\n fieldFavorite: 'Pinned',\n sensitivityNormal: 'normal',\n sensitivityHigh: 'high',\n favoriteHint: 'Show at top',\n rotationClearHint: '0 clears rotation',\n fieldColor: 'Color',\n fieldCustom: 'Custom fields (key=value per line)',\n error: 'Something went wrong.',\n kindLogin: 'Login',\n kindSsh: 'SSH',\n kindApiKey: 'API key',\n kindSecret: 'Secret',\n kindOauth: 'OAuth',\n kindCustom: 'Custom',\n} as const\n\nexport type VaultLocaleKey = keyof typeof en\n\n/** Chinese strings (same keys as English). */\nexport const zh: Record<VaultLocaleKey, string> = {\n nav: '凭据库',\n heading: 'Vault 凭据库',\n intro: '本机加密存储的凭据。',\n searchPlaceholder: '搜索标题、用户名、邮箱、主机…',\n loading: '加载中…',\n empty: '还没有凭据,添加一条开始使用。',\n emptyHint: '提示:你可以在对话中把 API Key 或 token 交给助手保存——开启自动捕获后,它会在你同意时帮你存入本库。批量导入?让助手调用 vault_import_csv 并给出 CSV 路径即可。',\n emptyHintReadonly: '当前为只读模式——只能读取凭据,不能在此添加。将 accessMode 改为 \"readwrite\" 即可启用写入。',\n modeLabel: '访问模式',\n autoCaptureLabel: '自动捕获对话中的凭据',\n modeReadonly: '只读',\n modeAsk: '写入前询问',\n modeAuto: '自动读写',\n modeReadonlyHint: '只读 —— 变更已禁用',\n modeAskHint: '写入前询问 —— 每次增/改/删都会征求你的确认',\n modeAutoHint: '自动读写 —— 无需逐次确认',\n autoCaptureOn: '自动捕获已开启',\n autoCaptureOff: '自动捕获已关闭',\n clearSearch: '清除搜索',\n entryCount: '条目数',\n reportTitle: '健康与轮换',\n recentActivity: '最近活动',\n recentlyAdded: '最近添加',\n reportRotation: '已过期 / 待轮换',\n reportWeak: '弱密码',\n reportReused: '跨条目复用的凭据',\n dupGroups: '重复分组',\n dupTitle: '重复条目',\n dupMerge: '合并',\n healthOk: '凭据库健康',\n healthBackup: '备份',\n backupNow: '立即备份',\n backupDone: '备份已创建',\n healthStrength: '强度',\n dueExpired: '已过期',\n dueExpiring: '将于',\n dueNow: '待轮换',\n showTrash: '回收站',\n hideTrash: '隐藏回收站',\n trashed: '已删除',\n trashEmpty: '回收站为空',\n restore: '恢复',\n clearTrash: '清空回收站',\n restoreAll: '全部恢复',\n clearTrashConfirm: '永久删除回收站中全部条目?此操作不可撤销。',\n show: '显示',\n hide: '隐藏',\n allKinds: '全部类型',\n allTags: '全部标签',\n sortAlpha: '排序:A–Z',\n sortRecent: '排序:最近',\n highSensitivity: '高敏',\n pinned: '已置顶',\n add: '新增凭据',\n quickAdd: '快速添加',\n cancel: '取消',\n save: '保存',\n edit: '编辑',\n delete: '删除',\n deleteConfirm: '确定删除该条目?此操作不可撤销。',\n copy: '复制',\n copyPassword: '复制密码',\n copyCode: '复制验证码',\n copied: '已复制',\n totp: '验证码',\n fieldTitle: '标题',\n fieldKind: '类型',\n fieldUsername: '用户名',\n fieldEmail: '邮箱',\n fieldPhone: '手机号',\n fieldPassword: '密码',\n fieldHost: '主机',\n fieldPort: '端口',\n fieldApiKey: 'API 密钥',\n fieldSecret: 'Secret',\n fieldAccessToken: '访问令牌',\n fieldRefreshToken: '刷新令牌',\n fieldOtpSecret: 'TOTP 密钥',\n fieldUrl: 'URL',\n fieldNotes: '备注',\n fieldTags: '标签',\n fieldIcon: '图标(emoji)',\n fieldExpiresAt: '过期时间',\n fieldRotationDays: '轮换周期(天,0=永不)',\n fieldSensitivity: '敏感级别',\n fieldFavorite: '置顶',\n sensitivityNormal: '普通',\n sensitivityHigh: '高敏',\n favoriteHint: '列表置顶显示',\n rotationClearHint: '0 清除轮换',\n fieldColor: '颜色',\n fieldCustom: '自定义字段(每行 key=value)',\n error: '操作失败。',\n kindLogin: '登录',\n kindSsh: 'SSH',\n kindApiKey: 'API 密钥',\n kindSecret: 'Secret',\n kindOauth: 'OAuth',\n kindCustom: '自定义',\n}\n","/**\n * dsh-vault browser half: a Vault settings page managing encrypted\n * credentials — list, search, add, edit, delete, and copy — through the host\n * VaultGateway remote over the /api RPC channel.\n *\n * @module dsh-vault/client\n */\n\nimport type { ClientContext } from '@deepseek-ai/dsh-client-runtime/client'\nimport type { ConnectionHandle } from '@deepseek-ai/dsh-api-remotes/client'\nimport type {} from '@deepseek-ai/dsh-client-locale/client'\nimport type {} from '@deepseek-ai/dsh-client-ui-settings/client'\nimport { VaultSection, type VaultSectionInjected } from './VaultSection.tsx'\nimport type { VaultSectionTypes } from './VaultSection.tsx'\nimport { en, zh, type VaultLocaleKey } from './locales.ts'\n\nexport type { VaultSectionInjected, VaultSectionProps } from './VaultSection.tsx'\nexport type { VaultSectionTypes } from './VaultSection.tsx'\nexport type { VaultLocaleKey } from './locales.ts'\n\ndeclare module '@deepseek-ai/dsh-client-ui-slots' {\n interface LocaleNamespaceMap {\n /** Vault settings page copy. */\n 'settings.vault': VaultLocaleKey\n }\n}\n\n/** Dictionary namespace owned by this plugin. */\nexport const NS = 'settings.vault'\n\n/** Services required by the Settings registration and the RPC face. */\nexport const inject = ['slots', 'locale', 'connection']\n\n/**\n * Register the Vault settings section once the `settings.section` declaration\n * is on the ledger. The section talks to the host through the connection RPC\n * channel (endpoints `vault/*` served by the host VaultGateway remote).\n */\nexport function apply(ctx: ClientContext): void {\n ctx.effect(() => ctx.locale.register(NS, { zh, en }), 'dsh-vault: dictionaries')\n\n const t = ctx.locale.bind(NS)\n const connection = ctx.get('connection') as ConnectionHandle\n\n /** Invoke one host vault remote and normalize the RPC envelope. */\n async function invoke<T>(method: string, args: Record<string, unknown> = {}): Promise<T> {\n const result = await connection.rpc.call('/api', `vault/${method}`, { args })\n if (!result.ok) {\n throw new Error(`vault.${method} failed: ${result.error.code}: ${result.error.message}`)\n }\n return result.value as T\n }\n\n const injected = (): VaultSectionInjected => ({\n t,\n config: () => invoke<VaultSectionTypes['config']>('config'),\n setAccessMode: (mode) => invoke<VaultSectionTypes['config']>('setAccessMode', { mode }),\n setAutoCapture: (enabled) => invoke<VaultSectionTypes['config']>('setAutoCapture', { enabled }),\n list: () => invoke<{ entries: VaultSectionTypes['entries'] }>('list').then(r => r.entries),\n search: (query, limit) => invoke<{ entries: VaultSectionTypes['entries'] }>('search', { query, limit: limit ?? 50 }).then(r => r.entries),\n get: (id) => invoke<{ found: boolean; entry?: VaultSectionTypes['fullEntry'] }>('get', { id }),\n add: (patch) => invoke<VaultSectionTypes['summaryEntry']>('add', { patch }),\n update: (id, patch) => invoke<{ found: boolean; entry?: VaultSectionTypes['summaryEntry'] }>('update', { id, patch }),\n remove: (id) => invoke<{ deleted: boolean }>('delete', { id }),\n trash: () => invoke<{ entries: VaultSectionTypes['entries'] }>('trash').then(r => r.entries),\n rotation: () => invoke<{ entries: unknown[] }>('rotation').then(r => r.entries),\n history: () => invoke<{ events: unknown[] }>('history').then(r => r.events),\n stats: () => invoke<Record<string, unknown>>('stats'),\n recent: () => invoke<{ entries: unknown[] }>('recent').then(r => r.entries),\n backupStatus: () => invoke<{ daysSinceBackup: number; backups: number }>('backupStatus'),\n backup: (maxBackups) => invoke<{ path: string; kept: number; pruned: number }>('backup', { maxBackups: maxBackups ?? 10 }),\n health: () => invoke<{ weak: unknown[]; reused: unknown[]; strength: { weak: number; fair: number; strong: number } }>('health'),\n duplicates: () => invoke<{ groups: number }>('duplicates'),\n duplicateGroups: () => invoke<Array<Array<{ id: string; title: string }>>>('duplicateGroups'),\n merge: (fromId, toId, keepSource) => invoke<{ found: boolean }>('merge', { fromId, toId, keepSource: keepSource ?? false }),\n restore: (id) => invoke<{ restored: boolean }>('restore', { id }),\n undeleteAll: () => invoke<{ restored: number }>('undeleteAll'),\n totp: (id) => invoke<{ code: string; label?: string; secondsRemaining: number }>('totp', { id }),\n })\n\n ctx.slots.inject('settings.section', () => ctx.slots.register({\n name: 'settings.section',\n id: 'vault',\n order: 30,\n label: () => t('nav'),\n inject: injected,\n }, VaultSection))\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"client.js","names":["css"],"sources":["../src/client/VaultSection.tsx","../src/client/locales.ts","../src/client/index.ts"],"sourcesContent":["/**\n * Vault settings section: list, search, add, edit, delete, and copy encrypted\n * credentials. All mutations go through the host VaultGateway remote; secrets\n * are shown only inside the edit form or a copy action, never in the list.\n */\n\nimport { useEffect, useId, useMemo, useState, type ReactNode } from 'react'\nimport type { PropsLocale, PropsRuntime, InjectFace, TranslateNS } from '@deepseek-ai/dsh-client-ui-slots'\nimport type { VaultLocaleKey } from './locales.ts'\nimport css from './VaultSection.module.css'\n\n/** Wire shapes shared with the host gateway (mirror of src/index.ts types). */\nexport interface VaultSummaryWire {\n id: string\n title: string\n sensitivity?: string\n kind?: string\n username?: string\n email?: string\n phone?: string\n host?: string\n port?: string\n url?: string\n tags?: string[]\n icon?: string\n color?: string\n}\n\nexport interface VaultFullWire {\n id: string\n title: string\n kind?: string\n username?: string\n email?: string\n phone?: string\n password?: string\n host?: string\n port?: string\n privateKey?: string\n apiKey?: string\n secret?: string\n accessToken?: string\n refreshToken?: string\n expiresAt?: number\n rotationDays?: number\n sensitivity?: string\n favorite?: boolean\n otpSecret?: string\n url?: string\n notes?: string\n tags?: string[]\n icon?: string\n color?: string\n fields?: Record<string, unknown>\n}\n\n/** Patch shape accepted by vault.add / vault.update. */\nexport type VaultPatch = Partial<Omit<VaultFullWire, 'id'>>\n\n/** Registration-side business face supplied by the plugin entry. */\nexport interface VaultSectionInjected {\n t: TranslateNS<'settings.vault'>\n config: () => Promise<{ accessMode: 'readonly' | 'ask' | 'auto'; autoCapture: boolean }>\n setAccessMode: (mode: 'readonly' | 'ask' | 'auto') => Promise<{ accessMode: 'readonly' | 'ask' | 'auto'; autoCapture: boolean }>\n setAutoCapture: (enabled: boolean) => Promise<{ accessMode: 'readonly' | 'ask' | 'auto'; autoCapture: boolean }>\n list: () => Promise<VaultSummaryWire[]>\n search: (query: string, limit?: number) => Promise<VaultSummaryWire[]>\n get: (id: string) => Promise<{ found: boolean; entry?: VaultFullWire }>\n add: (patch: VaultPatch & { title: string }) => Promise<VaultSummaryWire>\n update: (id: string, patch: VaultPatch) => Promise<{ found: boolean; entry?: VaultSummaryWire }>\n remove: (id: string) => Promise<{ deleted: boolean }>\n trash: () => Promise<VaultSummaryWire[]>\n rotation: () => Promise<unknown[]>\n history: () => Promise<unknown[]>\n stats: () => Promise<Record<string, unknown>>\n recent: () => Promise<unknown[]>\n backupStatus: () => Promise<{ daysSinceBackup: number; backups: number }>\n backup: (maxBackups?: number) => Promise<{ path: string; kept: number; pruned: number }>\n health: () => Promise<{ weak: unknown[]; reused: unknown[]; strength: { weak: number; fair: number; strong: number } }>\n duplicates: () => Promise<{ groups: number }>\n duplicateGroups: () => Promise<Array<Array<{ id: string; title: string }>>>\n status: () => Promise<{ locked: boolean; entries: number }>\n switchVault: (name: string) => Promise<{ switched: boolean; name: string }>\n listVaults: () => Promise<Array<{ name: string; active: boolean }>>\n touch: (id: string) => Promise<{ touched: boolean }>\n merge: (fromId: string, toId: string, keepSource?: boolean) => Promise<{ found: boolean }>\n restore: (id: string) => Promise<{ restored: boolean }>\n undeleteAll: () => Promise<{ restored: number }>\n totp: (id: string) => Promise<{ code: string; label?: string; secondsRemaining: number }>\n}\n\n/** Type-level alias so consumers can reference the wire shapes without values. */\nexport type VaultSectionTypes = {\n entries: VaultSummaryWire[]\n fullEntry: VaultFullWire\n summaryEntry: VaultSummaryWire\n config: { accessMode: 'readonly' | 'ask' | 'auto'; autoCapture: boolean }\n accessModes: Array<'readonly' | 'ask' | 'auto'>\n}\n\n/** Full component props assembled by the Settings slot renderer. */\nexport type VaultSectionProps =\n PropsRuntime<'settings.section'>\n & PropsLocale<'settings.vault'>\n & InjectFace<VaultSectionInjected>\n\n/** The editable form fields we render (subset of the full wire). */\ntype FormFields = {\n title?: string | undefined\n kind?: string | undefined\n username?: string | undefined\n email?: string | undefined\n phone?: string | undefined\n password?: string | undefined\n host?: string | undefined\n port?: string | undefined\n privateKey?: string | undefined\n apiKey?: string | undefined\n secret?: string | undefined\n accessToken?: string | undefined\n refreshToken?: string | undefined\n otpSecret?: string | undefined\n url?: string | undefined\n notes?: string | undefined\n icon?: string | undefined\n color?: string | undefined\n expiresAt?: number | undefined\n rotationDays?: number | undefined\n sensitivity?: string | undefined\n favorite?: boolean | undefined\n}\n\nconst FORM_FIELDS: Array<{ key: keyof FormFields; label: VaultLocaleKey }> = [\n { key: 'title', label: 'fieldTitle' },\n { key: 'kind', label: 'fieldKind' },\n { key: 'username', label: 'fieldUsername' },\n { key: 'email', label: 'fieldEmail' },\n { key: 'phone', label: 'fieldPhone' },\n { key: 'password', label: 'fieldPassword' },\n { key: 'host', label: 'fieldHost' },\n { key: 'port', label: 'fieldPort' },\n { key: 'apiKey', label: 'fieldApiKey' },\n { key: 'secret', label: 'fieldSecret' },\n { key: 'accessToken', label: 'fieldAccessToken' },\n { key: 'refreshToken', label: 'fieldRefreshToken' },\n { key: 'otpSecret', label: 'fieldOtpSecret' },\n { key: 'url', label: 'fieldUrl' },\n { key: 'notes', label: 'fieldNotes' },\n { key: 'expiresAt', label: 'fieldExpiresAt' },\n { key: 'rotationDays', label: 'fieldRotationDays' },\n { key: 'sensitivity', label: 'fieldSensitivity' },\n { key: 'favorite', label: 'fieldFavorite' },\n { key: 'icon', label: 'fieldIcon' },\n { key: 'color', label: 'fieldColor' },\n]\n\nconst KIND_KEYS: Record<string, VaultLocaleKey> = {\n login: 'kindLogin',\n ssh: 'kindSsh',\n 'api-key': 'kindApiKey',\n secret: 'kindSecret',\n oauth: 'kindOauth',\n custom: 'kindCustom',\n}\n\ntype ViewState =\n | { readonly status: 'loading' }\n | { readonly status: 'error' }\n | { readonly status: 'ready'; readonly entries: VaultSummaryWire[] }\n\ntype EditorState =\n | { readonly status: 'closed' }\n | { readonly status: 'creating' }\n | { readonly status: 'editing'; readonly entry: VaultFullWire }\n\nfunction emptyForm(): FormFields {\n return { title: '', kind: 'login', username: '', email: '', phone: '', password: '', host: '', port: '', icon: '', color: '' }\n}\n\n/** Render the Vault settings section. */\nexport function VaultSection(props: VaultSectionProps): ReactNode {\n 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 } = props\n const searchId = useId()\n const [query, setQuery] = useState('')\n const [state, setState] = useState<ViewState>({ status: 'loading' })\n const [editor, setEditor] = useState<EditorState>({ status: 'closed' })\n const [form, setForm] = useState<FormFields>(emptyForm())\n const [busy, setBusy] = useState(false)\n const [message, setMessage] = useState<string | null>(null)\n const [copiedId, setCopiedId] = useState<string | null>(null)\n const [totpMap, setTotpMap] = useState<Record<string, { code: string; until: number }>>({})\n const [nowTick, setNowTick] = useState(Date.now())\n const [tagsDraft, setTagsDraft] = useState('')\n const [fieldsDraft, setFieldsDraft] = useState('')\n const [revealed, setRevealed] = useState<Record<string, boolean>>({})\n const [kindFilter, setKindFilter] = useState('')\n const [tagFilter, setTagFilter] = useState('')\n const [expandedId, setExpandedId] = useState<string | null>(null)\n const [sortBy, setSortBy] = useState<'alpha' | 'recent'>('alpha')\n const [policy, setPolicy] = useState<{ accessMode: 'readonly' | 'ask' | 'auto'; autoCapture: boolean } | null>(null)\n const [showTrash, setShowTrash] = useState(false)\n const [trashEntries, setTrashEntries] = useState<VaultSummaryWire[]>([])\n const [report, setReport] = useState<{ rotation: unknown[]; weak: unknown[]; reused: unknown[]; strength: { weak: number; fair: number; strong: number } | null } | null>(null)\n const [dueMap, setDueMap] = useState<Record<string, { due: string; daysLeft: number }>>({})\n const [recentEvents, setRecentEvents] = useState<Array<Record<string, unknown>>>([])\n const [vaultStats, setVaultStats] = useState<Record<string, unknown> | null>(null)\n const [backupInfo, setBackupInfo] = useState<{ daysSinceBackup: number; backups: number } | null>(null)\n const [recentEntries, setRecentEntries] = useState<Array<Record<string, unknown>>>([])\n const [dupGroups, setDupGroups] = useState<number>(0)\n const [dupList, setDupList] = useState<Array<Array<{ id: string; title: string }>>>([])\n const [locked, setLocked] = useState(false)\n const [vaults, setVaults] = useState<Array<{ name: string; active: boolean }>>([])\n\n const readonly = policy?.accessMode === 'readonly'\n\n /** Switch the active vault and reload everything. */\n async function switchVaultTo(name: string): Promise<void> {\n setBusy(true)\n setMessage(null)\n try {\n await switchVault(name)\n await listVaults().then(setVaults)\n setQuery('')\n void refresh()\n status().then(value => setLocked(value.locked)).catch(() => {})\n } catch {\n setMessage(t('error'))\n } finally {\n setBusy(false)\n }\n }\n\n /** Merge one duplicate into another (first keeps gaps filled), then refresh. */\n async function mergeEntries(group: Array<{ id: string; title: string }>): Promise<void> {\n if (group.length < 2) return\n setBusy(true)\n setMessage(null)\n try {\n const [first, second] = group\n await merge(second!.id, first!.id, false)\n await duplicateGroups().then(setDupList)\n void refresh()\n } catch {\n setMessage(t('error'))\n } finally {\n setBusy(false)\n }\n }\n\n /** Run an encrypted backup now and refresh the backup-age badge. */\n async function backupNow(): Promise<void> {\n setBusy(true)\n setMessage(null)\n try {\n const result = await backup(10)\n setBackupInfo({ daysSinceBackup: 0, backups: result.kept })\n setMessage(`${t('backupDone')} (${result.kept} kept, ${result.pruned} pruned)`)\n void refresh()\n } catch {\n setMessage(t('error'))\n } finally {\n setBusy(false)\n }\n }\n\n useEffect(() => {\n let current = true\n void config().then(\n value => { if (current) setPolicy(value) },\n () => { /* policy is informational; ignore failures */ },\n )\n void status().then(\n value => { if (current) setLocked(value.locked) },\n () => { /* ignore */ },\n )\n void listVaults().then(setVaults).catch(() => {})\n return () => { current = false }\n }, [config, status, listVaults])\n\n const refresh = useMemo(() => async () => {\n setState({ status: 'loading' })\n try {\n const entries = query.trim().length === 0\n ? await list()\n : await search(query.trim())\n setState({ status: 'ready', entries })\n status().then(value => setLocked(value.locked)).catch(() => {})\n } catch {\n setState({ status: 'error' })\n }\n }, [list, search, query])\n\n useEffect(() => {\n let current = true\n const timer = window.setTimeout(() => {\n void refresh().then(\n () => { /* state already set inside refresh */ },\n () => { if (current) setState({ status: 'error' }) },\n )\n }, 250)\n return () => { current = false; window.clearTimeout(timer) }\n // refresh is memoized on query (debounced); list/search are stable.\n }, [refresh])\n\n // TOTP countdown: tick every second so the progress ring stays live, and\n // auto-refresh any code whose 30s window just expired.\n useEffect(() => {\n const timer = window.setInterval(() => setNowTick(Date.now()), 1000)\n return () => window.clearInterval(timer)\n }, [])\n\n useEffect(() => {\n for (const [id, info] of Object.entries(totpMap)) {\n if (info.until > 0 && nowTick >= info.until && info.code !== t('error')) {\n void totp(id).then(\n result => setTotpMap(previous => ({\n ...previous,\n [id]: { code: result.code, until: Date.now() + result.secondsRemaining * 1000 },\n })),\n () => { /* keep the last code; next window retries */ },\n )\n }\n }\n }, [nowTick, totpMap, totp])\n\n // Vault health & meta: load once on mount (stats, backup age, rotation,\n // weak/reused scan, recent activity) and refresh on window focus.\n useEffect(() => {\n let current = true\n const load = (): void => {\n void Promise.all([\n stats().catch(() => null),\n backupStatus().catch(() => null),\n rotation().catch(() => []),\n health().catch(() => null),\n recent().catch(() => []),\n duplicates().catch(() => null),\n ]).then(([st, bk, rot, hl, rc, dp]) => {\n if (dp !== null && typeof dp === 'object' && (dp as { groups?: number }).groups !== undefined) {\n setDupGroups((dp as { groups: number }).groups)\n }\n duplicateGroups().then(setDupList).catch(() => {})\n if (!current) return\n if (st !== null) setVaultStats(st as Record<string, unknown>)\n if (bk !== null) setBackupInfo(bk)\n setReport({ rotation: (rot ?? []) as unknown[], weak: ((hl?.weak ?? []) as unknown[]), reused: ((hl?.reused ?? []) as unknown[]), strength: (hl?.strength ?? null) as { weak: number; fair: number; strong: number } | null })\n const due: Record<string, { due: string; daysLeft: number }> = {}\n for (const item of (rot ?? []) as Array<{ id?: string; due?: string; daysLeft?: number }>) {\n if (item.id !== undefined && item.due !== undefined) due[item.id] = { due: item.due, daysLeft: item.daysLeft ?? 0 }\n }\n setDueMap(due)\n setRecentEntries((rc ?? []) as Array<Record<string, unknown>>)\n })\n }\n load()\n const onFocus = (): void => { load() }\n window.addEventListener('focus', onFocus)\n return () => { current = false; window.removeEventListener('focus', onFocus) }\n }, [stats, backupStatus, rotation, health, recent, duplicates, duplicateGroups])\n\n /** Open the editor for a new entry. */\n function startCreate(): void {\n setForm(emptyForm())\n setTagsDraft('')\n setFieldsDraft('')\n setMessage(null)\n setEditor({ status: 'creating' })\n }\n\n /** Open the editor for an existing entry (fetches full secrets). */\n async function startEdit(id: string): Promise<void> {\n setBusy(true)\n setMessage(null)\n try {\n const result = await get(id)\n if (!result.found || result.entry === undefined) {\n setMessage(t('error'))\n return\n }\n const entry = result.entry\n setForm({\n title: entry.title ?? '',\n kind: entry.kind ?? 'login',\n username: entry.username ?? '',\n email: entry.email ?? '',\n phone: entry.phone ?? '',\n password: entry.password ?? '',\n host: entry.host ?? '',\n port: entry.port ?? '',\n privateKey: entry.privateKey ?? '',\n apiKey: entry.apiKey ?? '',\n secret: entry.secret ?? '',\n accessToken: entry.accessToken ?? '',\n refreshToken: entry.refreshToken ?? '',\n otpSecret: entry.otpSecret ?? '',\n url: entry.url ?? '',\n notes: entry.notes ?? '',\n icon: entry.icon ?? '',\n color: entry.color ?? '',\n expiresAt: entry.expiresAt,\n rotationDays: entry.rotationDays,\n sensitivity: entry.sensitivity,\n favorite: entry.favorite ?? false,\n })\n setTagsDraft((entry.tags ?? []).join(', '))\n setFieldsDraft(entry.fields !== undefined ? Object.entries(entry.fields).map(([k, v]) => `${k}=${String(v)}`).join('\\n') : '')\n setEditor({ status: 'editing', entry })\n } catch {\n setMessage(t('error'))\n } finally {\n setBusy(false)\n }\n }\n\n /** Save the current form (create or update). */\n async function save(): Promise<void> {\n if (!(form.title ?? '').trim()) {\n setMessage(t('error'))\n return\n }\n setBusy(true)\n setMessage(null)\n try {\n const tags = tagsDraft.split(',').map(x => x.trim()).filter(x => x.length > 0)\n const fields: Record<string, string> = {}\n for (const line of fieldsDraft.split('\\n')) {\n const trimmed = line.trim()\n if (trimmed.length === 0) continue\n const eq = trimmed.indexOf('=')\n if (eq <= 0) continue\n fields[trimmed.slice(0, eq).trim()] = trimmed.slice(eq + 1).trim()\n }\n const patch: VaultPatch = {\n title: (form.title ?? '').trim(),\n ...(form.kind !== undefined ? { kind: form.kind } : {}),\n ...(form.username !== undefined ? { username: form.username } : {}),\n ...(form.email !== undefined ? { email: form.email } : {}),\n ...(form.phone !== undefined ? { phone: form.phone } : {}),\n ...(form.password !== undefined ? { password: form.password } : {}),\n ...(form.host !== undefined ? { host: form.host } : {}),\n ...(form.port !== undefined ? { port: form.port } : {}),\n ...(form.privateKey !== undefined ? { privateKey: form.privateKey } : {}),\n ...(form.apiKey !== undefined ? { apiKey: form.apiKey } : {}),\n ...(form.secret !== undefined ? { secret: form.secret } : {}),\n ...(form.accessToken !== undefined ? { accessToken: form.accessToken } : {}),\n ...(form.refreshToken !== undefined ? { refreshToken: form.refreshToken } : {}),\n ...(form.otpSecret !== undefined ? { otpSecret: form.otpSecret } : {}),\n ...(form.url !== undefined ? { url: form.url } : {}),\n ...(form.notes !== undefined ? { notes: form.notes } : {}),\n ...(form.icon !== undefined ? { icon: form.icon } : {}),\n ...(form.color !== undefined ? { color: form.color } : {}),\n ...(form.expiresAt !== undefined ? { expiresAt: form.expiresAt } : {}),\n ...(form.rotationDays !== undefined ? { rotationDays: form.rotationDays } : {}),\n ...(form.sensitivity !== undefined ? { sensitivity: form.sensitivity } : {}),\n ...(form.favorite !== undefined ? { favorite: form.favorite } : {}),\n // Always send tags: an empty array clears them, and the host store\n // treats empty string values as \"clear this field\" too.\n tags,\n fields,\n }\n if (editor.status === 'creating') {\n await add(patch as VaultPatch & { title: string })\n } else if (editor.status === 'editing') {\n await update(editor.entry.id, patch)\n }\n setEditor({ status: 'closed' })\n await refresh()\n } catch {\n setMessage(t('error'))\n } finally {\n setBusy(false)\n }\n }\n\n /** Delete an entry after confirmation. */\n async function removeEntry(id: string): Promise<void> {\n if (!window.confirm(t('deleteConfirm'))) return\n setBusy(true)\n try {\n await remove(id)\n await refresh()\n } catch {\n setMessage(t('error'))\n } finally {\n setBusy(false)\n }\n }\n\n /** Copy a field value to the clipboard and flash the row. */\n async function copyValue(id: string, value: string): Promise<void> {\n try {\n await navigator.clipboard.writeText(value)\n } catch {\n // Clipboard may be blocked; fall back to a temporary textarea.\n const textarea = document.createElement('textarea')\n textarea.value = value\n document.body.appendChild(textarea)\n textarea.select()\n document.execCommand('copy')\n textarea.remove()\n }\n setCopiedId(id)\n window.setTimeout(() => setCopiedId(null), 1500)\n }\n\n /** Fetch and display a TOTP code for an entry with an otpSecret. */\n async function showTotp(id: string): Promise<void> {\n setBusy(true)\n try {\n const result = await totp(id)\n setTotpMap(previous => ({ ...previous, [id]: { code: result.code, until: Date.now() + result.secondsRemaining * 1000 } }))\n } catch {\n setTotpMap(previous => ({ ...previous, [id]: { code: t('error'), until: 0 } }))\n } finally {\n setBusy(false)\n }\n }\n\n /** Field-set summary line for one entry (non-secret). */\n function kindIcon(kind?: string): string {\n switch (kind ?? 'login') {\n case 'ssh': return '🖥️'\n case 'api-key': return '🔑'\n case 'oauth': return '🔐'\n case 'secret': return '🤫'\n case 'custom': return '🧩'\n default: return '👤'\n }\n }\n\n function identityLine(entry: VaultSummaryWire): string {\n const parts = [\n entry.kind !== undefined ? t(KIND_KEYS[entry.kind] ?? 'kindCustom') : t('kindLogin'),\n entry.username,\n entry.email,\n entry.phone,\n entry.host !== undefined ? `${entry.host}${entry.port !== undefined ? `:${entry.port}` : ''}` : undefined,\n entry.url,\n ].filter((value): value is string => value !== undefined && value.length > 0)\n return parts.join(' · ')\n }\n\n return (\n <section className={css.section} aria-labelledby=\"vault-heading\">\n <h2 id=\"vault-heading\">{t('heading')}</h2>\n <p className={css.intro}>{t('intro')}</p>\n\n {locked && (\n <p role=\"alert\" className={css.lockedBanner}>{t('lockedBanner')}</p>\n )}\n\n <div className={css.toolbar}>\n {vaults.length > 0 && (\n <select\n className={css.kindFilter}\n value={vaults.find(v => v.active)?.name ?? ''}\n onChange={event => void switchVaultTo(event.target.value)}\n aria-label={t('vaultSelect')}\n >\n {vaults.map(v => (\n <option key={v.name} value={v.name}>{v.name}{v.active ? ' *' : ''}</option>\n ))}\n </select>\n )}\n <label className={css.searchBox}>\n <span className=\"sr-only\">{t('searchPlaceholder')}</span>\n <input\n id={searchId}\n type=\"search\"\n placeholder={t('searchPlaceholder')}\n value={query}\n onChange={event => setQuery(event.target.value)}\n />\n {query.length > 0 && (\n <button type=\"button\" className={css.clearButton} onClick={() => setQuery('')} aria-label={t('clearSearch')}>×</button>\n )}\n </label>\n <select className={css.kindFilter} value={kindFilter} onChange={e => setKindFilter(e.target.value)} aria-label={t('fieldKind')}>\n <option value=\"\">{t('allKinds')}</option>\n {Object.entries(KIND_KEYS).map(([value, key]) => (\n <option key={value} value={value}>{t(key)}</option>\n ))}\n </select>\n <select className={css.kindFilter} value={tagFilter} onChange={e => setTagFilter(e.target.value)} aria-label={t('fieldTags')}>\n <option value=\"\">{t('allTags')}</option>\n {[...new Set(state.status === 'ready' ? state.entries.flatMap(e => e.tags ?? []) : [])].sort().map(tag => (\n <option key={tag} value={tag}>{tag}</option>\n ))}\n </select>\n <button\n type=\"button\"\n className={css.sortButton}\n onClick={() => setSortBy(sortBy === 'alpha' ? 'recent' : 'alpha')}\n >{sortBy === 'alpha' ? t('sortAlpha') : t('sortRecent')}</button>\n <button type=\"button\" className={css.addButton} onClick={startCreate} disabled={busy || readonly}>\n + {t('add')}\n </button>\n </div>\n\n {policy !== null && (\n <div className={css.policyBar}>\n <label className={css.policyField}>\n <span>{t('modeLabel')}</span>\n <select\n value={policy.accessMode}\n disabled={busy}\n onChange={event => {\n const next = event.target.value as 'readonly' | 'ask' | 'auto'\n setBusy(true)\n setMessage(null)\n void setAccessMode(next).then(\n value => { setPolicy(value); setBusy(false) },\n () => { setMessage(t('error')); setBusy(false) },\n )\n }}\n >\n <option value=\"readonly\">{t('modeReadonly')}</option>\n <option value=\"ask\">{t('modeAsk')}</option>\n <option value=\"auto\">{t('modeAuto')}</option>\n </select>\n </label>\n <label className={css.policyField}>\n <span>{t('autoCaptureLabel')}</span>\n <input\n type=\"checkbox\"\n checked={policy.autoCapture}\n disabled={busy}\n onChange={event => {\n const next = event.target.checked\n setBusy(true)\n setMessage(null)\n void setAutoCapture(next).then(\n value => { setPolicy(value); setBusy(false) },\n () => { setMessage(t('error')); setBusy(false) },\n )\n }}\n />\n </label>\n <p className={policy.accessMode === 'readonly' ? css.modeReadonly : policy.accessMode === 'ask' ? css.modeAsk : css.modeAuto}>\n {policy.accessMode === 'readonly'\n ? t('modeReadonlyHint')\n : policy.accessMode === 'ask'\n ? t('modeAskHint')\n : t('modeAutoHint')}\n {policy.autoCapture ? ` · ${t('autoCaptureOn')}` : ` · ${t('autoCaptureOff')}`}\n </p>\n </div>\n )}\n\n {message !== null && <p role=\"alert\" className={css.error}>{message}</p>}\n\n {state.status === 'loading' && <p className={css.status}>{t('loading')}</p>}\n {state.status === 'error' && <p role=\"alert\" className={css.error}>{t('error')}</p>}\n {state.status === 'ready' && state.entries.length === 0 && (\n <div className={css.emptyBox}>\n <p className={css.empty}>{t('empty')}</p>\n <p className={css.emptyHint}>{readonly ? t('emptyHintReadonly') : t('emptyHint')}</p>\n {!readonly && (\n <button type=\"button\" className={css.addButton} onClick={startCreate}>{t('quickAdd')}</button>\n )}\n </div>\n )}\n\n {recentEntries.length > 0 && (\n <div className={css.reportBox}>\n <p className={css.reportTitle}>{t('recentlyAdded')}</p>\n {recentEntries.map((e, i) => (\n <p key={i} className={css.reportLine}>{String(e.title ?? '')}</p>\n ))}\n </div>\n )}\n\n {recentEvents.length > 0 && (\n <div className={css.reportBox}>\n <p className={css.reportTitle}>{t('recentActivity')}</p>\n {recentEvents.map((ev, i) => (\n <p key={i} className={css.reportLine}>\n {String(ev.action ?? '')} · {String(ev.title ?? ev.id ?? '')}\n </p>\n ))}\n </div>\n )}\n\n {report !== null && (report.rotation.length > 0 || report.weak.length > 0 || report.reused.length > 0) && (\n <div className={css.reportBox}>\n <p className={css.reportTitle}>{t('reportTitle')}</p>\n {report.rotation.length > 0 && (\n <>\n <p className={css.reportLine}>{t('reportRotation')}: {report.rotation.length}</p>\n {(report.rotation as Array<{ title?: string; due?: string; daysLeft?: number }>).slice(0, 8).map((item, i) => (\n <p key={i} className={css.reportSub}>\n · {String(item.title ?? '?')}{item.due === 'expired' ? ` (${t('dueExpired')})` : item.due === 'soon' ? ` (${t('dueExpiring')} ${item.daysLeft ?? 0}d)` : ` (${t('dueNow')})`}\n </p>\n ))}\n </>\n )}\n {report.weak.length > 0 && (\n <>\n <p className={css.reportLine}>{t('reportWeak')}: {report.weak.length}</p>\n {(report.weak as Array<{ title?: string }>).slice(0, 5).map((item, i) => (\n <p key={i} className={css.reportSub}>· {String(item.title ?? '?')}</p>\n ))}\n </>\n )}\n {report.reused.length > 0 && (\n <>\n <p className={css.reportLine}>{t('reportReused')}: {report.reused.length}</p>\n {(report.reused as Array<{ entries?: Array<{ title?: string }> }>).slice(0, 3).map((group, i) => (\n <p key={i} className={css.reportSub}>\n · {(group.entries ?? []).slice(0, 3).map(e => String(e.title ?? '?')).join(' / ')}\n </p>\n ))}\n </>\n )}\n </div>\n )}\n\n {dupList.length > 0 && (\n <div className={css.reportBox}>\n <p className={css.reportTitle}>{t('dupTitle')} ({dupList.length})</p>\n {dupList.slice(0, 5).map((group, gi) => (\n <div key={gi} className={css.dupGroup}>\n <span className={css.dupNames}>{group.map(g => g.title).join(' / ')}</span>\n <button\n type=\"button\"\n className={css.dupMerge}\n onClick={() => void mergeEntries(group)}\n disabled={busy || readonly}\n >{t('dupMerge')}</button>\n </div>\n ))}\n </div>\n )}\n\n {state.status === 'ready' && (state.entries.length > 0 || trashEntries.length > 0) && (\n <button\n type=\"button\"\n className={css.trashButton}\n onClick={() => {\n if (!showTrash) void trash().then(setTrashEntries)\n setShowTrash(!showTrash)\n }}\n >{showTrash ? t('hideTrash') : t('showTrash')}{trashEntries.length > 0 ? ` (${trashEntries.length})` : ''}</button>\n )}\n\n {showTrash && (\n <ul className={css.list}>\n {trashEntries.map(entry => (\n <li key={entry.id} className={css.row}>\n <div className={css.rowMain}>\n <span className={css.title}>{entry.title}</span>\n <span className={css.identity}>{t('trashed')}</span>\n </div>\n <div className={css.rowActions}>\n <button\n type=\"button\"\n onClick={() => { void restore(entry.id).then(() => { void trash().then(setTrashEntries); void refresh() }) }}\n disabled={busy || readonly}\n >{t('restore')}</button>\n </div>\n </li>\n ))}\n {trashEntries.length === 0 && <p className={css.empty}>{t('trashEmpty')}</p>}\n </ul>\n )}\n {showTrash && trashEntries.length > 0 && (\n <>\n <button\n type=\"button\"\n className={css.trashButton}\n onClick={() => {\n setBusy(true)\n void undeleteAll().then(() => {\n void trash().then(setTrashEntries)\n void refresh()\n setBusy(false)\n }, () => setBusy(false))\n }}\n disabled={busy || readonly}\n >{t('restoreAll')}</button>\n <button\n type=\"button\"\n className={css.dangerButton}\n onClick={() => {\n if (!window.confirm(t('clearTrashConfirm'))) return\n setBusy(true)\n void Promise.all(trashEntries.map(e => remove(e.id))).then(() => {\n void trash().then(setTrashEntries)\n void refresh()\n setBusy(false)\n }, () => setBusy(false))\n }}\n disabled={busy || readonly}\n >{t('clearTrash')}</button>\n </>\n )}\n\n {state.status === 'ready' && state.entries.length > 0 && (\n <ul className={css.list}>\n {state.entries.filter(entry => (kindFilter === '' || entry.kind === kindFilter) && (tagFilter === '' || (entry.tags ?? []).includes(tagFilter))).sort((a, b) => sortBy === 'alpha' ? a.title.localeCompare(b.title) : 0).map(entry => {\n const totpInfo = totpMap[entry.id]\n const remaining = totpInfo !== undefined && totpInfo.until > 0 ? Math.max(0, Math.ceil((totpInfo.until - nowTick) / 1000)) : undefined\n const frac = remaining !== undefined ? remaining / 30 : 0\n const code = totpInfo?.code\n return (\n <li key={entry.id} className={`${css.row}${dueMap[entry.id] !== undefined ? ` ${dueMap[entry.id]!.due === 'expired' ? css.rowExpired : css.rowDue}` : ''}`}>\n <div className={css.rowMain} onClick={() => setExpandedId(expandedId === entry.id ? null : entry.id)}>\n <span className={css.title} style={entry.color !== undefined && entry.color !== '' ? { borderLeft: `3px solid ${entry.color}`, paddingLeft: 6 } : undefined}>\n <span className={css.kindIcon}>{entry.icon ?? kindIcon(entry.kind)}</span>\n {(entry as VaultSummaryWire & { favorite?: boolean }).favorite && (\n <span className={css.pinStar} title={t('pinned')}>★</span>\n )}\n {entry.title}\n {(entry as VaultSummaryWire & { sensitivity?: string }).sensitivity === 'high' && (\n <span className={css.highBadge}>{t('highSensitivity')}</span>\n )}\n {dueMap[entry.id] !== undefined && (\n <span className={`${css.dueBadge} ${dueMap[entry.id]!.due === 'expired' ? css.badgeDanger : css.badgeWarn}`}>\n {dueMap[entry.id]!.due === 'expired' ? t('dueExpired') : dueMap[entry.id]!.due === 'soon' ? `${t('dueExpiring')} ${dueMap[entry.id]!.daysLeft}d` : t('dueNow')}\n </span>\n )}\n </span>\n <span className={css.identity}>{identityLine(entry)}</span>\n {code !== undefined && (\n <span className={css.totp}>\n <svg className={css.totpRing} width=\"16\" height=\"16\" viewBox=\"0 0 16 16\" aria-hidden=\"true\">\n <circle cx=\"8\" cy=\"8\" r=\"6.5\" fill=\"none\" stroke=\"var(--dsh-color-border, #ddd)\" strokeWidth=\"2\" />\n <circle\n cx=\"8\" cy=\"8\" r=\"6.5\" fill=\"none\"\n stroke={remaining !== undefined && remaining <= 5 ? '#cf3d3d' : '#2e9e5b'}\n strokeWidth=\"2\" strokeLinecap=\"round\"\n strokeDasharray={`${(frac * 2 * Math.PI * 6.5).toFixed(1)} ${(2 * Math.PI * 6.5).toFixed(1)}`}\n transform=\"rotate(-90 8 8)\"\n />\n </svg>\n {code}{remaining !== undefined ? ` (${remaining}s)` : ''}\n </span>\n )}\n </div>\n {expandedId === entry.id && (\n <div className={css.detailBox}>\n {Object.entries(entry).filter(([k]) => !['id', 'title'].includes(k) && entry[k as keyof VaultSummaryWire] !== undefined).map(([k, v]) => (\n <span key={k} className={css.detailItem}>\n <strong>{k}</strong>: {Array.isArray(v) ? v.join(', ') : String(v)}\n </span>\n ))}\n </div>\n )}\n <div className={css.rowActions}>\n {copiedId === entry.id && <span className={css.copied}>{t('copied')}</span>}\n <button\n type=\"button\"\n onClick={() => void copyValue(entry.id, entry.username ?? entry.title)}\n disabled={busy}\n >{t('copy')}</button>\n <button\n type=\"button\"\n onClick={() => {\n setBusy(true)\n void get(entry.id).then(r => {\n if (r.found && r.entry?.password) void copyValue(entry.id, r.entry.password)\n setBusy(false)\n }, () => setBusy(false))\n }}\n disabled={busy || readonly}\n >{t('copyPassword')}</button>\n <button type=\"button\" onClick={() => void showTotp(entry.id)} disabled={busy}>{t('totp')}</button>\n {code !== undefined && (\n <button type=\"button\" onClick={() => void copyValue(entry.id, code)} disabled={busy}>{t('copyCode')}</button>\n )}\n <button type=\"button\" onClick={() => void touch(entry.id).then(() => void refresh())} disabled={busy || readonly} title={t('touchHint')}>{t('touch')}</button>\n <button type=\"button\" onClick={() => void startEdit(entry.id)} disabled={busy || readonly}>{t('edit')}</button>\n <button\n type=\"button\"\n className={css.deleteButton}\n onClick={() => void removeEntry(entry.id)}\n disabled={busy || readonly}\n >{t('delete')}</button>\n </div>\n </li>\n )\n })}\n </ul>\n )}\n\n {state.status === 'ready' && (\n <div className={css.healthBar}>\n {vaultStats !== null && typeof vaultStats.total === 'number' && (\n <span className={css.badge}>{t('entryCount')}: {String(vaultStats.total)}</span>\n )}\n {vaultStats !== null && typeof vaultStats.withTotp === 'number' && (\n <span className={css.badge}>TOTP: {String(vaultStats.withTotp)}</span>\n )}\n {vaultStats !== null && typeof vaultStats.highSensitivity === 'number' && (\n <span className={css.badge}>{t('highSensitivity')}: {String(vaultStats.highSensitivity)}</span>\n )}\n {report !== null && report.strength !== null && (\n <span className={`${css.badge} ${report.strength.weak > 0 ? css.badgeDanger : css.badgeOk}`}>\n {t('healthStrength')}: {report.strength.weak}W/{report.strength.fair}F/{report.strength.strong}S\n </span>\n )}\n {report !== null && report.rotation.length > 0 && (\n <span className={`${css.badge} ${css.badgeWarn}`}>{t('reportRotation')}: {report.rotation.length}</span>\n )}\n {report !== null && report.weak.length > 0 && (\n <span className={`${css.badge} ${css.badgeDanger}`}>{t('reportWeak')}: {report.weak.length}</span>\n )}\n {report !== null && report.reused.length > 0 && (\n <span className={`${css.badge} ${css.badgeDanger}`}>{t('reportReused')}: {report.reused.length}</span>\n )}\n {dupGroups > 0 && (\n <span className={`${css.badge} ${css.badgeWarn}`}>{t('dupGroups')}: {dupGroups}</span>\n )}\n {report !== null && report.rotation.length === 0 && report.weak.length === 0 && report.reused.length === 0 && (\n <span className={`${css.badge} ${css.badgeOk}`}>{t('healthOk')}</span>\n )}\n {backupInfo !== null && backupInfo.daysSinceBackup >= 0 && (\n <span className={`${css.badge} ${backupInfo.daysSinceBackup > 14 ? css.badgeDanger : backupInfo.daysSinceBackup > 7 ? css.badgeWarn : ''}`}>\n {t('healthBackup')}: {backupInfo.daysSinceBackup}d\n </span>\n )}\n <button type=\"button\" className={css.backupButton} onClick={() => void backupNow()} disabled={busy}>\n {t('backupNow')}\n </button>\n </div>\n )}\n {state.status === 'ready' && (\n <p className={css.footer}>\n {t('entryCount')}: {state.entries.length}\n {vaultStats !== null && typeof vaultStats.withTotp === 'number' && ` · TOTP: ${String(vaultStats.withTotp)}`}\n {vaultStats !== null && typeof vaultStats.highSensitivity === 'number' && ` · ${t('highSensitivity')}: ${String(vaultStats.highSensitivity)}`}\n {backupInfo !== null && backupInfo.daysSinceBackup >= 0 && ` · backup: ${backupInfo.daysSinceBackup}d ago`}\n {vaultStats !== null && typeof vaultStats.byTag === 'object' && vaultStats.byTag !== null\n && Object.keys(vaultStats.byTag as Record<string, unknown>).length > 0\n && ` · tags: ${Object.entries(vaultStats.byTag as Record<string, unknown>).map(([k, v]) => `${k}(${String(v)})`).join(' ')}`}\n </p>\n )}\n\n {editor.status !== 'closed' && (\n <div className={css.editor} role=\"dialog\" aria-label={editor.status === 'creating' ? t('add') : t('edit')}>\n <div className={css.editorBody}>\n {FORM_FIELDS.map(field => (\n <label key={field.key} className={css.field}>\n <span>{t(field.label)}</span>\n {field.key === 'kind' ? (\n <select\n value={form.kind ?? 'login'}\n onChange={event => setForm(previous => ({ ...previous, kind: event.target.value }))}\n >\n {Object.entries(KIND_KEYS).map(([value, key]) => (\n <option key={value} value={value}>{t(key)}</option>\n ))}\n </select>\n ) : field.key === 'title' ? (\n <input\n value={form.title ?? ''}\n onChange={event => setForm(previous => ({ ...previous, title: event.target.value }))}\n />\n ) : field.key === 'password' || field.key === 'otpSecret' || field.key === 'apiKey'\n || field.key === 'secret' || field.key === 'accessToken' || field.key === 'refreshToken'\n || field.key === 'privateKey' ? (\n <span className={css.secretField}>\n <input\n type={revealed[field.key] ? 'text' : 'password'}\n value={(form[field.key] as string | undefined) ?? ''}\n onChange={event => setForm(previous => ({ ...previous, [field.key]: event.target.value }))}\n />\n <button\n type=\"button\"\n className={css.revealButton}\n onClick={() => setRevealed(previous => ({ ...previous, [field.key]: !previous[field.key] }))}\n >{revealed[field.key] ? t('hide') : t('show')}</button>\n </span>\n ) : field.key === 'expiresAt' ? (\n <input\n type=\"datetime-local\"\n value={form.expiresAt !== undefined ? new Date(form.expiresAt).toISOString().slice(0, 16) : ''}\n onChange={event => {\n const raw = event.target.value\n const epoch = raw.length > 0 ? Date.parse(raw) : NaN\n setForm(previous => ({ ...previous, expiresAt: Number.isNaN(epoch) ? undefined : epoch }))\n }}\n />\n ) : field.key === 'rotationDays' ? (\n <input\n type=\"number\"\n min={0}\n max={3650}\n placeholder={t('rotationClearHint')}\n value={form.rotationDays ?? ''}\n onChange={event => {\n const raw = event.target.value\n setForm(previous => ({ ...previous, rotationDays: raw.length > 0 ? Number(raw) : undefined }))\n }}\n />\n ) : field.key === 'sensitivity' ? (\n <select\n value={form.sensitivity ?? 'normal'}\n onChange={event => setForm(previous => ({ ...previous, sensitivity: event.target.value === 'high' ? 'high' : 'normal' }))}\n >\n <option value=\"normal\">{t('sensitivityNormal')}</option>\n <option value=\"high\">{t('sensitivityHigh')}</option>\n </select>\n ) : field.key === 'favorite' ? (\n <label className={css.checkField}>\n <input\n type=\"checkbox\"\n checked={form.favorite ?? false}\n onChange={event => setForm(previous => ({ ...previous, favorite: event.target.checked }))}\n />\n {t('favoriteHint')}\n </label>\n ) : (\n <input\n type=\"text\"\n value={(form[field.key] as string | undefined) ?? ''}\n onChange={event => setForm(previous => ({ ...previous, [field.key]: event.target.value }))}\n />\n )}\n </label>\n ))}\n <label className={css.field}>\n <span>{t('fieldTags')}</span>\n <input\n value={tagsDraft}\n onChange={event => setTagsDraft(event.target.value)}\n placeholder=\"dev, prod\"\n />\n </label>\n <label className={css.field}>\n <span>{t('fieldCustom')}</span>\n <textarea\n value={fieldsDraft}\n onChange={event => setFieldsDraft(event.target.value)}\n rows={3}\n placeholder=\"region=us-east-1 team=infra\"\n />\n </label>\n </div>\n <div className={css.editorActions}>\n <button type=\"button\" onClick={() => setEditor({ status: 'closed' })} disabled={busy}>{t('cancel')}</button>\n <button type=\"button\" className={css.saveButton} onClick={() => void save()} disabled={busy}>{t('save')}</button>\n </div>\n </div>\n )}\n </section>\n )\n}\n","/** Copy dictionaries for the Vault settings section. */\n\n/** English strings (the key-set source of truth for this pair). */\nexport const en = {\n nav: 'Vault',\n heading: 'Vault',\n intro: 'Encrypted credentials stored on this machine.',\n searchPlaceholder: 'Search title, username, email, host…',\n loading: 'Loading…',\n empty: 'No credentials yet. Add one to get started.',\n emptyHint: 'Tip: you can ask the assistant to save an API key or token you share in chat — with auto-capture on it offers to store it for you. Bulk importing? Ask for vault_import_csv with a CSV file path.',\n emptyHintReadonly: 'The vault is in readonly mode — credentials can be read but not added here. Switch accessMode to \"readwrite\" to enable writes.',\n modeLabel: 'Access mode',\n autoCaptureLabel: 'Auto-capture credentials from chat',\n modeReadonly: 'Read-only',\n modeAsk: 'Ask before writing',\n modeAuto: 'Automatic read-write',\n modeReadonlyHint: 'Read-only — mutations disabled',\n modeAskHint: 'Prompt before writing — every add/update/delete asks you',\n modeAutoHint: 'Automatic read-write — no per-call prompt',\n autoCaptureOn: 'auto-capture on',\n autoCaptureOff: 'auto-capture off',\n clearSearch: 'Clear search',\n entryCount: 'Entries',\n reportTitle: 'Health & rotation',\n recentActivity: 'Recent activity',\n recentlyAdded: 'Recently added',\n reportRotation: 'expired / due for rotation',\n reportWeak: 'weak passwords',\n reportReused: 'credentials reused across entries',\n dupGroups: 'duplicate groups',\n dupTitle: 'Duplicate entries',\n dupMerge: 'Merge',\n healthOk: 'vault healthy',\n healthBackup: 'backup',\n backupNow: 'Backup now',\n backupDone: 'Backup created',\n lockedBanner: 'Vault is locked — unlock it with vault_unlock to read or write entries.',\n vaultSelect: 'Active vault',\n touch: 'Used',\n touchHint: 'Mark as recently used',\n healthStrength: 'strength',\n dueExpired: 'EXPIRED',\n dueExpiring: 'expires in',\n dueNow: 'rotation due',\n showTrash: 'Trash',\n hideTrash: 'Hide trash',\n trashed: 'in trash',\n trashEmpty: 'Trash is empty',\n restore: 'Restore',\n clearTrash: 'Empty trash',\n restoreAll: 'Restore all',\n clearTrashConfirm: 'Permanently delete ALL trashed entries? This cannot be undone.',\n show: 'Show',\n hide: 'Hide',\n allKinds: 'All kinds',\n allTags: 'All tags',\n sortAlpha: 'Sort: A–Z',\n sortRecent: 'Sort: recent',\n highSensitivity: 'HIGH',\n pinned: 'Pinned',\n add: 'Add credential',\n quickAdd: 'Quick add',\n cancel: 'Cancel',\n save: 'Save',\n edit: 'Edit',\n delete: 'Delete',\n deleteConfirm: 'Delete this entry? This cannot be undone.',\n copy: 'Copy',\n copyPassword: 'Copy password',\n copyCode: 'Copy code',\n copied: 'Copied',\n totp: 'Code',\n fieldTitle: 'Title',\n fieldKind: 'Kind',\n fieldUsername: 'Username',\n fieldEmail: 'Email',\n fieldPhone: 'Phone',\n fieldPassword: 'Password',\n fieldHost: 'Host',\n fieldPort: 'Port',\n fieldApiKey: 'API key',\n fieldSecret: 'Secret',\n fieldAccessToken: 'Access token',\n fieldRefreshToken: 'Refresh token',\n fieldOtpSecret: 'OTP secret',\n fieldUrl: 'URL',\n fieldNotes: 'Notes',\n fieldTags: 'Tags',\n fieldIcon: 'Icon (emoji)',\n fieldExpiresAt: 'Expires at',\n fieldRotationDays: 'Rotation (days, 0 = never)',\n fieldSensitivity: 'Sensitivity',\n fieldFavorite: 'Pinned',\n sensitivityNormal: 'normal',\n sensitivityHigh: 'high',\n favoriteHint: 'Show at top',\n rotationClearHint: '0 clears rotation',\n fieldColor: 'Color',\n fieldCustom: 'Custom fields (key=value per line)',\n error: 'Something went wrong.',\n kindLogin: 'Login',\n kindSsh: 'SSH',\n kindApiKey: 'API key',\n kindSecret: 'Secret',\n kindOauth: 'OAuth',\n kindCustom: 'Custom',\n} as const\n\nexport type VaultLocaleKey = keyof typeof en\n\n/** Chinese strings (same keys as English). */\nexport const zh: Record<VaultLocaleKey, string> = {\n nav: '凭据库',\n heading: 'Vault 凭据库',\n intro: '本机加密存储的凭据。',\n searchPlaceholder: '搜索标题、用户名、邮箱、主机…',\n loading: '加载中…',\n empty: '还没有凭据,添加一条开始使用。',\n emptyHint: '提示:你可以在对话中把 API Key 或 token 交给助手保存——开启自动捕获后,它会在你同意时帮你存入本库。批量导入?让助手调用 vault_import_csv 并给出 CSV 路径即可。',\n emptyHintReadonly: '当前为只读模式——只能读取凭据,不能在此添加。将 accessMode 改为 \"readwrite\" 即可启用写入。',\n modeLabel: '访问模式',\n autoCaptureLabel: '自动捕获对话中的凭据',\n modeReadonly: '只读',\n modeAsk: '写入前询问',\n modeAuto: '自动读写',\n modeReadonlyHint: '只读 —— 变更已禁用',\n modeAskHint: '写入前询问 —— 每次增/改/删都会征求你的确认',\n modeAutoHint: '自动读写 —— 无需逐次确认',\n autoCaptureOn: '自动捕获已开启',\n autoCaptureOff: '自动捕获已关闭',\n clearSearch: '清除搜索',\n entryCount: '条目数',\n reportTitle: '健康与轮换',\n recentActivity: '最近活动',\n recentlyAdded: '最近添加',\n reportRotation: '已过期 / 待轮换',\n reportWeak: '弱密码',\n reportReused: '跨条目复用的凭据',\n dupGroups: '重复分组',\n dupTitle: '重复条目',\n dupMerge: '合并',\n healthOk: '凭据库健康',\n healthBackup: '备份',\n backupNow: '立即备份',\n backupDone: '备份已创建',\n lockedBanner: '保险库已锁定 —— 请使用 vault_unlock 解锁后再读写条目。',\n vaultSelect: '当前保险库',\n touch: '标记已用',\n touchHint: '标记为最近使用',\n healthStrength: '强度',\n dueExpired: '已过期',\n dueExpiring: '将于',\n dueNow: '待轮换',\n showTrash: '回收站',\n hideTrash: '隐藏回收站',\n trashed: '已删除',\n trashEmpty: '回收站为空',\n restore: '恢复',\n clearTrash: '清空回收站',\n restoreAll: '全部恢复',\n clearTrashConfirm: '永久删除回收站中全部条目?此操作不可撤销。',\n show: '显示',\n hide: '隐藏',\n allKinds: '全部类型',\n allTags: '全部标签',\n sortAlpha: '排序:A–Z',\n sortRecent: '排序:最近',\n highSensitivity: '高敏',\n pinned: '已置顶',\n add: '新增凭据',\n quickAdd: '快速添加',\n cancel: '取消',\n save: '保存',\n edit: '编辑',\n delete: '删除',\n deleteConfirm: '确定删除该条目?此操作不可撤销。',\n copy: '复制',\n copyPassword: '复制密码',\n copyCode: '复制验证码',\n copied: '已复制',\n totp: '验证码',\n fieldTitle: '标题',\n fieldKind: '类型',\n fieldUsername: '用户名',\n fieldEmail: '邮箱',\n fieldPhone: '手机号',\n fieldPassword: '密码',\n fieldHost: '主机',\n fieldPort: '端口',\n fieldApiKey: 'API 密钥',\n fieldSecret: 'Secret',\n fieldAccessToken: '访问令牌',\n fieldRefreshToken: '刷新令牌',\n fieldOtpSecret: 'TOTP 密钥',\n fieldUrl: 'URL',\n fieldNotes: '备注',\n fieldTags: '标签',\n fieldIcon: '图标(emoji)',\n fieldExpiresAt: '过期时间',\n fieldRotationDays: '轮换周期(天,0=永不)',\n fieldSensitivity: '敏感级别',\n fieldFavorite: '置顶',\n sensitivityNormal: '普通',\n sensitivityHigh: '高敏',\n favoriteHint: '列表置顶显示',\n rotationClearHint: '0 清除轮换',\n fieldColor: '颜色',\n fieldCustom: '自定义字段(每行 key=value)',\n error: '操作失败。',\n kindLogin: '登录',\n kindSsh: 'SSH',\n kindApiKey: 'API 密钥',\n kindSecret: 'Secret',\n kindOauth: 'OAuth',\n kindCustom: '自定义',\n}\n","/**\n * dsh-vault browser half: a Vault settings page managing encrypted\n * credentials — list, search, add, edit, delete, and copy — through the host\n * VaultGateway remote over the /api RPC channel.\n *\n * @module dsh-vault/client\n */\n\nimport type { ClientContext } from '@deepseek-ai/dsh-client-runtime/client'\nimport type { ConnectionHandle } from '@deepseek-ai/dsh-api-remotes/client'\nimport type {} from '@deepseek-ai/dsh-client-locale/client'\nimport type {} from '@deepseek-ai/dsh-client-ui-settings/client'\nimport { VaultSection, type VaultSectionInjected } from './VaultSection.tsx'\nimport type { VaultSectionTypes } from './VaultSection.tsx'\nimport { en, zh, type VaultLocaleKey } from './locales.ts'\n\nexport type { VaultSectionInjected, VaultSectionProps } from './VaultSection.tsx'\nexport type { VaultSectionTypes } from './VaultSection.tsx'\nexport type { VaultLocaleKey } from './locales.ts'\n\ndeclare module '@deepseek-ai/dsh-client-ui-slots' {\n interface LocaleNamespaceMap {\n /** Vault settings page copy. */\n 'settings.vault': VaultLocaleKey\n }\n}\n\n/** Dictionary namespace owned by this plugin. */\nexport const NS = 'settings.vault'\n\n/** Services required by the Settings registration and the RPC face. */\nexport const inject = ['slots', 'locale', 'connection']\n\n/**\n * Register the Vault settings section once the `settings.section` declaration\n * is on the ledger. The section talks to the host through the connection RPC\n * channel (endpoints `vault/*` served by the host VaultGateway remote).\n */\nexport function apply(ctx: ClientContext): void {\n ctx.effect(() => ctx.locale.register(NS, { zh, en }), 'dsh-vault: dictionaries')\n\n const t = ctx.locale.bind(NS)\n const connection = ctx.get('connection') as ConnectionHandle\n\n /** Invoke one host vault remote and normalize the RPC envelope. */\n async function invoke<T>(method: string, args: Record<string, unknown> = {}): Promise<T> {\n const result = await connection.rpc.call('/api', `vault/${method}`, { args })\n if (!result.ok) {\n throw new Error(`vault.${method} failed: ${result.error.code}: ${result.error.message}`)\n }\n return result.value as T\n }\n\n const injected = (): VaultSectionInjected => ({\n t,\n config: () => invoke<VaultSectionTypes['config']>('config'),\n setAccessMode: (mode) => invoke<VaultSectionTypes['config']>('setAccessMode', { mode }),\n setAutoCapture: (enabled) => invoke<VaultSectionTypes['config']>('setAutoCapture', { enabled }),\n list: () => invoke<{ entries: VaultSectionTypes['entries'] }>('list').then(r => r.entries),\n search: (query, limit) => invoke<{ entries: VaultSectionTypes['entries'] }>('search', { query, limit: limit ?? 50 }).then(r => r.entries),\n get: (id) => invoke<{ found: boolean; entry?: VaultSectionTypes['fullEntry'] }>('get', { id }),\n add: (patch) => invoke<VaultSectionTypes['summaryEntry']>('add', { patch }),\n update: (id, patch) => invoke<{ found: boolean; entry?: VaultSectionTypes['summaryEntry'] }>('update', { id, patch }),\n remove: (id) => invoke<{ deleted: boolean }>('delete', { id }),\n trash: () => invoke<{ entries: VaultSectionTypes['entries'] }>('trash').then(r => r.entries),\n rotation: () => invoke<{ entries: unknown[] }>('rotation').then(r => r.entries),\n history: () => invoke<{ events: unknown[] }>('history').then(r => r.events),\n stats: () => invoke<Record<string, unknown>>('stats'),\n recent: () => invoke<{ entries: unknown[] }>('recent').then(r => r.entries),\n backupStatus: () => invoke<{ daysSinceBackup: number; backups: number }>('backupStatus'),\n backup: (maxBackups) => invoke<{ path: string; kept: number; pruned: number }>('backup', { maxBackups: maxBackups ?? 10 }),\n health: () => invoke<{ weak: unknown[]; reused: unknown[]; strength: { weak: number; fair: number; strong: number } }>('health'),\n duplicates: () => invoke<{ groups: number }>('duplicates'),\n status: () => invoke<{ locked: boolean; entries: number }>('status'),\n switchVault: (name) => invoke<{ switched: boolean; name: string }>('switchVault', { name }),\n listVaults: () => invoke<Array<{ name: string; active: boolean }>>('listVaults'),\n touch: (id) => invoke<{ touched: boolean }>('touch', { id }),\n duplicateGroups: () => invoke<Array<Array<{ id: string; title: string }>>>('duplicateGroups'),\n merge: (fromId, toId, keepSource) => invoke<{ found: boolean }>('merge', { fromId, toId, keepSource: keepSource ?? false }),\n restore: (id) => invoke<{ restored: boolean }>('restore', { id }),\n undeleteAll: () => invoke<{ restored: number }>('undeleteAll'),\n totp: (id) => invoke<{ code: string; label?: string; secondsRemaining: number }>('totp', { id }),\n })\n\n ctx.slots.inject('settings.section', () => ctx.slots.register({\n name: 'settings.section',\n id: 'vault',\n order: 30,\n label: () => t('nav'),\n inject: injected,\n }, VaultSection))\n}\n"],"mappings":"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"}
|
package/lib/index.js
CHANGED
|
@@ -1213,7 +1213,7 @@ export async function apply(ctx, config) {
|
|
|
1213
1213
|
description: 'Report how many days have passed since the last vault-backup-* file was written '
|
|
1214
1214
|
+ '(1Password-style backup reminder). Returns daysSinceBackup and a suggestion.',
|
|
1215
1215
|
parameters: {},
|
|
1216
|
-
output: { schema: { type: 'object', additionalProperties: false, properties: { daysSinceBackup: { type: 'integer', required: true }, backups: { type: 'integer', required: true } } }, render: (_a, v) => [{ type: 'text', text: `last backup ${v.daysSinceBackup} days ago (${v.backups} backup file(s))` }] },
|
|
1216
|
+
output: { schema: { type: 'object', additionalProperties: false, properties: { daysSinceBackup: { type: 'integer', required: true }, backups: { type: 'integer', required: true }, lastBackupAt: { type: 'integer' } } }, render: (_a, v) => [{ type: 'text', text: `last backup ${v.daysSinceBackup} days ago (${v.backups} backup file(s))` }] },
|
|
1217
1217
|
async execute() {
|
|
1218
1218
|
const s = await guardStore();
|
|
1219
1219
|
const dir = dirname(resolveVaultPath(config));
|
|
@@ -1230,7 +1230,7 @@ export async function apply(ctx, config) {
|
|
|
1230
1230
|
const last = backups.length > 0 ? Math.max(...backups) : 0;
|
|
1231
1231
|
const days = last > 0 ? Math.floor((Date.now() - last) / 86_400_000) : -1;
|
|
1232
1232
|
void s;
|
|
1233
|
-
return { daysSinceBackup: days, backups: backups.length };
|
|
1233
|
+
return { daysSinceBackup: days, backups: backups.length, ...(last > 0 ? { lastBackupAt: last } : {}) };
|
|
1234
1234
|
},
|
|
1235
1235
|
}));
|
|
1236
1236
|
// ── vault_bulk_export: JSON dump of all entries (non-encrypted) ─────────────
|
|
@@ -1347,6 +1347,8 @@ export async function apply(ctx, config) {
|
|
|
1347
1347
|
parameters: {
|
|
1348
1348
|
secret: { type: 'string', required: true, description: 'The secret value to store.' },
|
|
1349
1349
|
note: { type: 'string', description: 'Optional context note.' },
|
|
1350
|
+
title: { type: 'string', description: 'Optional explicit title; defaults to secret-YYYY-MM-DD-NNNN.' },
|
|
1351
|
+
kind: { type: 'string', enum: ['login', 'ssh', 'api-key', 'secret', 'oauth', 'custom'], description: 'Entry kind (default secret).' },
|
|
1350
1352
|
},
|
|
1351
1353
|
output: { schema: { type: 'object', additionalProperties: false, properties: { id: { type: 'string', required: true }, title: { type: 'string', required: true } } }, render: (_a, v) => [{ type: 'text', text: `saved as "${v.title}" (id: ${v.id})` }] },
|
|
1352
1354
|
async execute(args) {
|
|
@@ -1355,10 +1357,12 @@ export async function apply(ctx, config) {
|
|
|
1355
1357
|
throw new Error('vault_note_secret: secret is required');
|
|
1356
1358
|
const s = await guardStore();
|
|
1357
1359
|
const stamp = new Date().toISOString().slice(0, 10);
|
|
1358
|
-
const title =
|
|
1360
|
+
const title = typeof args.title === 'string' && args.title.trim().length > 0
|
|
1361
|
+
? args.title.trim()
|
|
1362
|
+
: `secret-${stamp}-${Math.floor(Math.random() * 9000 + 1000)}`;
|
|
1359
1363
|
const entry = await s.add({
|
|
1360
1364
|
title,
|
|
1361
|
-
kind: 'secret',
|
|
1365
|
+
kind: args.kind ?? 'secret',
|
|
1362
1366
|
secret: args.secret,
|
|
1363
1367
|
...(args.note !== undefined ? { notes: args.note } : {}),
|
|
1364
1368
|
});
|
|
@@ -1573,7 +1577,10 @@ export async function apply(ctx, config) {
|
|
|
1573
1577
|
name: 'vault_import_browser',
|
|
1574
1578
|
description: 'Import a browser password-manager CSV (name,url,username,password — Chrome/Firefox/'
|
|
1575
1579
|
+ 'Edge export format). Rows without a name are skipped; returns added/skipped counts.',
|
|
1576
|
-
parameters: {
|
|
1580
|
+
parameters: {
|
|
1581
|
+
path: { type: 'string', required: true, description: 'Absolute path of the browser CSV.' },
|
|
1582
|
+
overwrite: { type: 'boolean', description: 'Update existing entries with the same name instead of skipping (default false).' },
|
|
1583
|
+
},
|
|
1577
1584
|
output: { schema: { type: 'object', additionalProperties: false, properties: { added: { type: 'integer', required: true }, skipped: { type: 'integer', required: true }, updated: { type: 'integer', required: true } } }, render: (_a, v) => [{ type: 'text', text: `imported ${v.added}, updated ${v.updated}, skipped ${v.skipped}` }] },
|
|
1578
1585
|
async execute(args) {
|
|
1579
1586
|
assertWritable('vault_import_browser');
|
|
@@ -1613,15 +1620,28 @@ export async function apply(ctx, config) {
|
|
|
1613
1620
|
...(idx.username >= 0 && idx.username < row.length && row[idx.username] ? { username: row[idx.username] } : {}),
|
|
1614
1621
|
...(idx.password >= 0 && idx.password < row.length && row[idx.password] ? { password: row[idx.password] } : {}),
|
|
1615
1622
|
};
|
|
1616
|
-
|
|
1623
|
+
const existing = s.list().find(e => e.title === name);
|
|
1624
|
+
if (existing && !args.overwrite) {
|
|
1617
1625
|
skipped++;
|
|
1618
1626
|
continue;
|
|
1619
1627
|
}
|
|
1628
|
+
if (existing && args.overwrite) {
|
|
1629
|
+
const patch = {};
|
|
1630
|
+
if (entry.url !== undefined)
|
|
1631
|
+
patch.url = entry.url;
|
|
1632
|
+
if (entry.username !== undefined)
|
|
1633
|
+
patch.username = entry.username;
|
|
1634
|
+
if (entry.password !== undefined)
|
|
1635
|
+
patch.password = entry.password;
|
|
1636
|
+
await s.update(existing.id, patch);
|
|
1637
|
+
updated++;
|
|
1638
|
+
continue;
|
|
1639
|
+
}
|
|
1620
1640
|
s.insertDirect(entry);
|
|
1621
1641
|
added++;
|
|
1622
1642
|
}
|
|
1623
1643
|
await s.persist();
|
|
1624
|
-
return { added, skipped, updated
|
|
1644
|
+
return { added, skipped, updated };
|
|
1625
1645
|
},
|
|
1626
1646
|
}));
|
|
1627
1647
|
// ── vault_autofill_check: does a target have usable credentials? ────────────
|
|
@@ -1759,14 +1779,21 @@ export async function apply(ctx, config) {
|
|
|
1759
1779
|
ids: { type: 'array', required: true, items: { type: 'string' }, description: 'Entry ids.' },
|
|
1760
1780
|
fields: { type: 'array', items: { type: 'string' }, description: 'Fields to include per entry (e.g. ["username", "password"]).' },
|
|
1761
1781
|
},
|
|
1762
|
-
output: { schema: { type: 'object', additionalProperties: false, properties: { entries: { type: 'array', required: true, items: { type: 'json' } } } }, render: (_a, v) => [{ type: 'text', text: `returned ${v.entries.length} entries` }] },
|
|
1782
|
+
output: { schema: { type: 'object', additionalProperties: false, properties: { entries: { type: 'array', required: true, items: { type: 'json' } }, missing: { type: 'array', required: true, items: { type: 'string' } } } }, render: (_a, v) => [{ type: 'text', text: `returned ${v.entries.length} entries` }] },
|
|
1763
1783
|
async execute(args) {
|
|
1764
1784
|
const s = await guardStore();
|
|
1765
1785
|
const out = [];
|
|
1786
|
+
const missing = [];
|
|
1787
|
+
const seen = new Set();
|
|
1766
1788
|
for (const id of args.ids ?? []) {
|
|
1789
|
+
if (seen.has(id))
|
|
1790
|
+
continue;
|
|
1791
|
+
seen.add(id);
|
|
1767
1792
|
const e = s.get(id);
|
|
1768
|
-
if (!e)
|
|
1793
|
+
if (!e) {
|
|
1794
|
+
missing.push(id);
|
|
1769
1795
|
continue;
|
|
1796
|
+
}
|
|
1770
1797
|
const full = stripTimestamps(e);
|
|
1771
1798
|
if (Array.isArray(args.fields) && args.fields.length > 0) {
|
|
1772
1799
|
const picked = {};
|
|
@@ -1780,7 +1807,7 @@ export async function apply(ctx, config) {
|
|
|
1780
1807
|
out.push(full);
|
|
1781
1808
|
}
|
|
1782
1809
|
}
|
|
1783
|
-
return { entries: out };
|
|
1810
|
+
return { entries: out, missing };
|
|
1784
1811
|
},
|
|
1785
1812
|
}));
|
|
1786
1813
|
// ── vault_import_wallet: import from a pass directory ──────────────────────
|
|
@@ -2021,13 +2048,39 @@ export async function apply(ctx, config) {
|
|
|
2021
2048
|
async execute(args) {
|
|
2022
2049
|
const s = await guardStore();
|
|
2023
2050
|
const needle = args.target.trim().toLowerCase();
|
|
2051
|
+
if (needle.length === 0)
|
|
2052
|
+
return { found: false };
|
|
2053
|
+
const scoreOf = (entry) => {
|
|
2054
|
+
const host = (entry.host ?? '').toLowerCase();
|
|
2055
|
+
const url = (entry.url ?? '').toLowerCase();
|
|
2056
|
+
const title = entry.title.toLowerCase();
|
|
2057
|
+
const username = (entry.username ?? '').toLowerCase();
|
|
2058
|
+
const email = (entry.email ?? '').toLowerCase();
|
|
2059
|
+
const hostBase = host.split(':')[0] ?? '';
|
|
2060
|
+
if (hostBase !== '' && hostBase === needle)
|
|
2061
|
+
return 6;
|
|
2062
|
+
if (url !== '' && url === needle)
|
|
2063
|
+
return 5;
|
|
2064
|
+
if (title === needle)
|
|
2065
|
+
return 4;
|
|
2066
|
+
if (hostBase !== '' && hostBase.includes(needle))
|
|
2067
|
+
return 3;
|
|
2068
|
+
if (url.includes(needle))
|
|
2069
|
+
return 2;
|
|
2070
|
+
if (title.includes(needle) || username.includes(needle) || email.includes(needle))
|
|
2071
|
+
return 1;
|
|
2072
|
+
return 0;
|
|
2073
|
+
};
|
|
2074
|
+
let best;
|
|
2075
|
+
let bestScore = 0;
|
|
2024
2076
|
for (const entry of s.list()) {
|
|
2025
|
-
const
|
|
2026
|
-
if (
|
|
2027
|
-
|
|
2077
|
+
const score = scoreOf(entry);
|
|
2078
|
+
if (score > bestScore) {
|
|
2079
|
+
best = entry;
|
|
2080
|
+
bestScore = score;
|
|
2028
2081
|
}
|
|
2029
2082
|
}
|
|
2030
|
-
return { found: false };
|
|
2083
|
+
return best === undefined ? { found: false } : { found: true, entry: stripTimestamps(best) };
|
|
2031
2084
|
},
|
|
2032
2085
|
}));
|
|
2033
2086
|
// ── vault_env: environment-variable export ─────────────────────────────────
|
|
@@ -2116,12 +2169,17 @@ export async function apply(ctx, config) {
|
|
|
2116
2169
|
path: { type: 'string', description: 'Optional absolute output path; defaults to <vault dir>/vault-export-<ts>.csv.' },
|
|
2117
2170
|
kind: { type: 'string', description: 'Only export entries of this kind (login/ssh/api-key/secret/oauth/custom).', enum: ['login', 'ssh', 'api-key', 'secret', 'oauth', 'custom'] },
|
|
2118
2171
|
includeSecrets: { type: 'boolean', description: 'Include secret columns (password/apiKey/secret/tokens). Default false — the CSV is secret-free for safe handling.' },
|
|
2172
|
+
favoriteOnly: { type: 'boolean', description: 'Only export pinned (favorite) entries.' },
|
|
2173
|
+
tag: { type: 'string', description: 'Only export entries carrying this tag.' },
|
|
2119
2174
|
},
|
|
2120
2175
|
output: { schema: { type: 'object', additionalProperties: false, properties: { path: { type: 'string', required: true }, count: { type: 'integer', required: true } } }, render: (_a, v) => [{ type: 'text', text: `exported ${v.count} entries to ${v.path}` }] },
|
|
2121
2176
|
async execute(args) {
|
|
2122
2177
|
const s = await guardStore();
|
|
2123
2178
|
const kind = args.kind;
|
|
2124
|
-
const
|
|
2179
|
+
const tag = typeof args.tag === 'string' ? args.tag.trim() : '';
|
|
2180
|
+
const entries = s.list().filter(e => (kind === undefined || (e.kind ?? 'login') === kind)
|
|
2181
|
+
&& (args.favoriteOnly !== true || e.favorite === true)
|
|
2182
|
+
&& (tag.length === 0 || (e.tags ?? []).includes(tag)));
|
|
2125
2183
|
const secretFields = ['password', 'apiKey', 'secret', 'accessToken', 'refreshToken', 'otpSecret', 'privateKey'];
|
|
2126
2184
|
const metaFields = ['url', 'email', 'phone', 'host', 'port', 'expiresAt', 'rotationDays', 'notes', 'tags', 'sensitivity', 'favorite', 'icon', 'color'];
|
|
2127
2185
|
const fields = args.includeSecrets === true
|
|
@@ -2387,6 +2445,10 @@ let VaultGateway = (() => {
|
|
|
2387
2445
|
let _health_decorators;
|
|
2388
2446
|
let _duplicates_decorators;
|
|
2389
2447
|
let _duplicateGroups_decorators;
|
|
2448
|
+
let _status_decorators;
|
|
2449
|
+
let _switchVault_decorators;
|
|
2450
|
+
let _listVaults_decorators;
|
|
2451
|
+
let _touch_decorators;
|
|
2390
2452
|
let _merge_decorators;
|
|
2391
2453
|
let _get_decorators;
|
|
2392
2454
|
let _search_decorators;
|
|
@@ -2413,6 +2475,10 @@ let VaultGateway = (() => {
|
|
|
2413
2475
|
_health_decorators = [Remote('health')];
|
|
2414
2476
|
_duplicates_decorators = [Remote('duplicates')];
|
|
2415
2477
|
_duplicateGroups_decorators = [Remote('duplicateGroups')];
|
|
2478
|
+
_status_decorators = [Remote('status')];
|
|
2479
|
+
_switchVault_decorators = [Remote('switchVault')];
|
|
2480
|
+
_listVaults_decorators = [Remote('listVaults')];
|
|
2481
|
+
_touch_decorators = [Remote('touch')];
|
|
2416
2482
|
_merge_decorators = [Remote('merge')];
|
|
2417
2483
|
_get_decorators = [Remote('get')];
|
|
2418
2484
|
_search_decorators = [Remote('search')];
|
|
@@ -2436,6 +2502,10 @@ let VaultGateway = (() => {
|
|
|
2436
2502
|
__esDecorate(this, null, _health_decorators, { kind: "method", name: "health", static: false, private: false, access: { has: obj => "health" in obj, get: obj => obj.health }, metadata: _metadata }, null, _instanceExtraInitializers);
|
|
2437
2503
|
__esDecorate(this, null, _duplicates_decorators, { kind: "method", name: "duplicates", static: false, private: false, access: { has: obj => "duplicates" in obj, get: obj => obj.duplicates }, metadata: _metadata }, null, _instanceExtraInitializers);
|
|
2438
2504
|
__esDecorate(this, null, _duplicateGroups_decorators, { kind: "method", name: "duplicateGroups", static: false, private: false, access: { has: obj => "duplicateGroups" in obj, get: obj => obj.duplicateGroups }, metadata: _metadata }, null, _instanceExtraInitializers);
|
|
2505
|
+
__esDecorate(this, null, _status_decorators, { kind: "method", name: "status", static: false, private: false, access: { has: obj => "status" in obj, get: obj => obj.status }, metadata: _metadata }, null, _instanceExtraInitializers);
|
|
2506
|
+
__esDecorate(this, null, _switchVault_decorators, { kind: "method", name: "switchVault", static: false, private: false, access: { has: obj => "switchVault" in obj, get: obj => obj.switchVault }, metadata: _metadata }, null, _instanceExtraInitializers);
|
|
2507
|
+
__esDecorate(this, null, _listVaults_decorators, { kind: "method", name: "listVaults", static: false, private: false, access: { has: obj => "listVaults" in obj, get: obj => obj.listVaults }, metadata: _metadata }, null, _instanceExtraInitializers);
|
|
2508
|
+
__esDecorate(this, null, _touch_decorators, { kind: "method", name: "touch", static: false, private: false, access: { has: obj => "touch" in obj, get: obj => obj.touch }, metadata: _metadata }, null, _instanceExtraInitializers);
|
|
2439
2509
|
__esDecorate(this, null, _merge_decorators, { kind: "method", name: "merge", static: false, private: false, access: { has: obj => "merge" in obj, get: obj => obj.merge }, metadata: _metadata }, null, _instanceExtraInitializers);
|
|
2440
2510
|
__esDecorate(this, null, _get_decorators, { kind: "method", name: "get", static: false, private: false, access: { has: obj => "get" in obj, get: obj => obj.get }, metadata: _metadata }, null, _instanceExtraInitializers);
|
|
2441
2511
|
__esDecorate(this, null, _search_decorators, { kind: "method", name: "search", static: false, private: false, access: { has: obj => "search" in obj, get: obj => obj.search }, metadata: _metadata }, null, _instanceExtraInitializers);
|
|
@@ -2451,18 +2521,20 @@ let VaultGateway = (() => {
|
|
|
2451
2521
|
vaultName;
|
|
2452
2522
|
accessPolicy;
|
|
2453
2523
|
backupRetention;
|
|
2524
|
+
activeName;
|
|
2454
2525
|
constructor(ctx, config) {
|
|
2455
2526
|
super(ctx, 'vault');
|
|
2456
2527
|
this.masterPassword = config.masterPassword ?? resolveMasterPassword(config);
|
|
2457
2528
|
this.vaultPath = config.path;
|
|
2458
2529
|
this.vaultName = config.name;
|
|
2530
|
+
this.activeName = config.name;
|
|
2459
2531
|
this.accessPolicy = config.accessPolicy ?? { mode: config.accessMode ?? 'ask', autoCapture: config.autoCapture ?? false };
|
|
2460
2532
|
this.backupRetention = config.backupRetention ?? 10;
|
|
2461
2533
|
}
|
|
2462
2534
|
async ensureStore() {
|
|
2463
2535
|
return sharedVaultStore(this.masterPassword, {
|
|
2464
2536
|
...(this.vaultPath !== undefined ? { path: this.vaultPath } : {}),
|
|
2465
|
-
...(this.
|
|
2537
|
+
...(this.activeName !== undefined ? { name: this.activeName } : {}),
|
|
2466
2538
|
});
|
|
2467
2539
|
}
|
|
2468
2540
|
/** Reject mutations when the vault is in readonly mode (UI surface). */
|
|
@@ -2619,6 +2691,44 @@ let VaultGateway = (() => {
|
|
|
2619
2691
|
}
|
|
2620
2692
|
return [...byKey.values()].filter(g => g.length > 1);
|
|
2621
2693
|
}
|
|
2694
|
+
/** Vault lock/entry status for the UI banner. */
|
|
2695
|
+
async status() {
|
|
2696
|
+
const store = await this.ensureStore();
|
|
2697
|
+
return { locked: store.isLocked, entries: store.isLocked ? 0 : store.list().length };
|
|
2698
|
+
}
|
|
2699
|
+
/** Switch the active vault by name (same master password), then re-open. */
|
|
2700
|
+
async switchVault(name) {
|
|
2701
|
+
if (typeof name !== 'string' || name.trim().length === 0 || /[^A-Za-z0-9._-]/.test(name)) {
|
|
2702
|
+
throw new Error('vault: invalid vault name');
|
|
2703
|
+
}
|
|
2704
|
+
this.activeName = name.trim();
|
|
2705
|
+
await this.ensureStore();
|
|
2706
|
+
return { switched: true, name: this.activeName };
|
|
2707
|
+
}
|
|
2708
|
+
/** List available vault files (one .json per vault, excluding access/meta/exports). */
|
|
2709
|
+
async listVaults() {
|
|
2710
|
+
const dir = dirname(this.vaultPath ?? defaultVaultPath(this.activeName));
|
|
2711
|
+
const names = [];
|
|
2712
|
+
try {
|
|
2713
|
+
const entries = await readdir(dir);
|
|
2714
|
+
for (const entry of entries) {
|
|
2715
|
+
const m = /^(.*)\.json$/.exec(entry);
|
|
2716
|
+
if (!m)
|
|
2717
|
+
continue;
|
|
2718
|
+
if (['access', 'meta'].includes(m[1]) || m[1].startsWith('vault-export-'))
|
|
2719
|
+
continue;
|
|
2720
|
+
names.push(m[1]);
|
|
2721
|
+
}
|
|
2722
|
+
}
|
|
2723
|
+
catch { /* no dir yet */ }
|
|
2724
|
+
return names.sort().map(name => ({ name, active: name === this.activeName }));
|
|
2725
|
+
}
|
|
2726
|
+
/** Mark an entry as recently used (touches updatedAt). */
|
|
2727
|
+
async touch(id) {
|
|
2728
|
+
const store = await this.ensureStore();
|
|
2729
|
+
const updated = await store.markUsed(id);
|
|
2730
|
+
return { touched: updated !== undefined };
|
|
2731
|
+
}
|
|
2622
2732
|
/** Merge one entry into another (Bitwarden-style dedup); keepSource optional. */
|
|
2623
2733
|
async merge(fromId, toId, keepSource) {
|
|
2624
2734
|
const store = await this.ensureStore();
|
package/lib/store.js
CHANGED
|
@@ -386,7 +386,9 @@ export class VaultStore {
|
|
|
386
386
|
continue;
|
|
387
387
|
report.push({ ...toSummary(entry), due, daysLeft });
|
|
388
388
|
}
|
|
389
|
-
|
|
389
|
+
// Most urgent first: expired < rotation-due < soon, then fewest days left.
|
|
390
|
+
const severity = { expired: 0, due: 1, soon: 2 };
|
|
391
|
+
return report.sort((a, b) => severity[a.due] - severity[b.due] || a.daysLeft - b.daysLeft);
|
|
390
392
|
}
|
|
391
393
|
/** Advanced multi-criteria search: title/username/kind/tag text + created-after. */
|
|
392
394
|
advancedSearch(criteria) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dsh-vault",
|
|
3
|
-
"version": "0.9.
|
|
3
|
+
"version": "0.9.5",
|
|
4
4
|
"description": "Encrypted credential vault for DeepSeek Harness: store and retrieve usernames, emails, phone numbers, passwords, TOTP secrets, SSH/API-key/OAuth developer credentials through model tools and a Settings UI page.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|