dsh-vault 0.8.1 → 0.8.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/client.js +56 -38
- package/lib/client.js.map +1 -1
- package/lib/index.js +68 -1
- package/package.json +1 -1
package/lib/client.js
CHANGED
|
@@ -17,51 +17,51 @@ window.__ModuleLoader__.load({
|
|
|
17
17
|
document.head.appendChild(tag);
|
|
18
18
|
}
|
|
19
19
|
var VaultSection_module_css_default = {
|
|
20
|
-
"
|
|
21
|
-
"
|
|
22
|
-
"
|
|
23
|
-
"
|
|
24
|
-
"
|
|
25
|
-
"policyBar": "t_j5va_policyBar",
|
|
26
|
-
"pinStar": "t_j5va_pinStar",
|
|
27
|
-
"totp": "t_j5va_totp",
|
|
20
|
+
"revealButton": "t_j5va_revealButton",
|
|
21
|
+
"modeAuto": "t_j5va_modeAuto",
|
|
22
|
+
"addButton": "t_j5va_addButton",
|
|
23
|
+
"deleteButton": "t_j5va_deleteButton",
|
|
24
|
+
"emptyHint": "t_j5va_emptyHint",
|
|
28
25
|
"dangerButton": "t_j5va_dangerButton",
|
|
29
|
-
"
|
|
26
|
+
"row": "t_j5va_row",
|
|
27
|
+
"toolbar": "t_j5va_toolbar",
|
|
30
28
|
"copied": "t_j5va_copied",
|
|
31
|
-
"
|
|
32
|
-
"
|
|
33
|
-
"emptyHint": "t_j5va_emptyHint",
|
|
34
|
-
"rowMain": "t_j5va_rowMain",
|
|
29
|
+
"kindFilter": "t_j5va_kindFilter",
|
|
30
|
+
"empty": "t_j5va_empty",
|
|
35
31
|
"error": "t_j5va_error",
|
|
36
|
-
"
|
|
37
|
-
"
|
|
38
|
-
"
|
|
39
|
-
"saveButton": "t_j5va_saveButton",
|
|
40
|
-
"toolbar": "t_j5va_toolbar",
|
|
41
|
-
"editorActions": "t_j5va_editorActions",
|
|
32
|
+
"reportTitle": "t_j5va_reportTitle",
|
|
33
|
+
"modeAsk": "t_j5va_modeAsk",
|
|
34
|
+
"section": "t_j5va_section",
|
|
42
35
|
"reportLine": "t_j5va_reportLine",
|
|
43
|
-
"
|
|
36
|
+
"detailBox": "t_j5va_detailBox",
|
|
44
37
|
"clearButton": "t_j5va_clearButton",
|
|
45
|
-
"
|
|
46
|
-
"addButton": "t_j5va_addButton",
|
|
38
|
+
"modeReadonly": "t_j5va_modeReadonly",
|
|
47
39
|
"footer": "t_j5va_footer",
|
|
48
|
-
"list": "t_j5va_list",
|
|
49
|
-
"emptyBox": "t_j5va_emptyBox",
|
|
50
|
-
"secretField": "t_j5va_secretField",
|
|
51
|
-
"row": "t_j5va_row",
|
|
52
|
-
"highBadge": "t_j5va_highBadge",
|
|
53
|
-
"identity": "t_j5va_identity",
|
|
54
|
-
"section": "t_j5va_section",
|
|
55
|
-
"title": "t_j5va_title",
|
|
56
|
-
"sortButton": "t_j5va_sortButton",
|
|
57
|
-
"detailItem": "t_j5va_detailItem",
|
|
58
|
-
"revealButton": "t_j5va_revealButton",
|
|
59
|
-
"deleteButton": "t_j5va_deleteButton",
|
|
60
|
-
"modeAuto": "t_j5va_modeAuto",
|
|
61
40
|
"searchBox": "t_j5va_searchBox",
|
|
41
|
+
"policyField": "t_j5va_policyField",
|
|
62
42
|
"reportBox": "t_j5va_reportBox",
|
|
43
|
+
"kindIcon": "t_j5va_kindIcon",
|
|
44
|
+
"detailItem": "t_j5va_detailItem",
|
|
45
|
+
"highBadge": "t_j5va_highBadge",
|
|
46
|
+
"field": "t_j5va_field",
|
|
47
|
+
"pinStar": "t_j5va_pinStar",
|
|
48
|
+
"title": "t_j5va_title",
|
|
63
49
|
"editor": "t_j5va_editor",
|
|
64
|
-
"
|
|
50
|
+
"intro": "t_j5va_intro",
|
|
51
|
+
"editorBody": "t_j5va_editorBody",
|
|
52
|
+
"totp": "t_j5va_totp",
|
|
53
|
+
"rowMain": "t_j5va_rowMain",
|
|
54
|
+
"identity": "t_j5va_identity",
|
|
55
|
+
"status": "t_j5va_status",
|
|
56
|
+
"editorActions": "t_j5va_editorActions",
|
|
57
|
+
"saveButton": "t_j5va_saveButton",
|
|
58
|
+
"policyBar": "t_j5va_policyBar",
|
|
59
|
+
"emptyBox": "t_j5va_emptyBox",
|
|
60
|
+
"rowActions": "t_j5va_rowActions",
|
|
61
|
+
"trashButton": "t_j5va_trashButton",
|
|
62
|
+
"sortButton": "t_j5va_sortButton",
|
|
63
|
+
"list": "t_j5va_list",
|
|
64
|
+
"secretField": "t_j5va_secretField"
|
|
65
65
|
};
|
|
66
66
|
//#endregion
|
|
67
67
|
//#region src/client/VaultSection.tsx
|
|
@@ -130,6 +130,14 @@ window.__ModuleLoader__.load({
|
|
|
130
130
|
{
|
|
131
131
|
key: "notes",
|
|
132
132
|
label: "fieldNotes"
|
|
133
|
+
},
|
|
134
|
+
{
|
|
135
|
+
key: "icon",
|
|
136
|
+
label: "fieldIcon"
|
|
137
|
+
},
|
|
138
|
+
{
|
|
139
|
+
key: "color",
|
|
140
|
+
label: "fieldColor"
|
|
133
141
|
}
|
|
134
142
|
];
|
|
135
143
|
const KIND_KEYS = {
|
|
@@ -149,7 +157,9 @@ window.__ModuleLoader__.load({
|
|
|
149
157
|
phone: "",
|
|
150
158
|
password: "",
|
|
151
159
|
host: "",
|
|
152
|
-
port: ""
|
|
160
|
+
port: "",
|
|
161
|
+
icon: "",
|
|
162
|
+
color: ""
|
|
153
163
|
};
|
|
154
164
|
}
|
|
155
165
|
/** Render the Vault settings section. */
|
|
@@ -250,7 +260,9 @@ window.__ModuleLoader__.load({
|
|
|
250
260
|
refreshToken: entry.refreshToken ?? "",
|
|
251
261
|
otpSecret: entry.otpSecret ?? "",
|
|
252
262
|
url: entry.url ?? "",
|
|
253
|
-
notes: entry.notes ?? ""
|
|
263
|
+
notes: entry.notes ?? "",
|
|
264
|
+
icon: entry.icon ?? "",
|
|
265
|
+
color: entry.color ?? ""
|
|
254
266
|
});
|
|
255
267
|
setTagsDraft((entry.tags ?? []).join(", "));
|
|
256
268
|
setFieldsDraft(entry.fields !== void 0 ? Object.entries(entry.fields).map(([k, v]) => `${k}=${String(v)}`).join("\n") : "");
|
|
@@ -299,6 +311,8 @@ window.__ModuleLoader__.load({
|
|
|
299
311
|
...form.otpSecret !== void 0 ? { otpSecret: form.otpSecret } : {},
|
|
300
312
|
...form.url !== void 0 ? { url: form.url } : {},
|
|
301
313
|
...form.notes !== void 0 ? { notes: form.notes } : {},
|
|
314
|
+
...form.icon !== void 0 ? { icon: form.icon } : {},
|
|
315
|
+
...form.color !== void 0 ? { color: form.color } : {},
|
|
302
316
|
tags,
|
|
303
317
|
fields
|
|
304
318
|
};
|
|
@@ -930,6 +944,8 @@ window.__ModuleLoader__.load({
|
|
|
930
944
|
fieldUrl: "URL",
|
|
931
945
|
fieldNotes: "Notes",
|
|
932
946
|
fieldTags: "Tags",
|
|
947
|
+
fieldIcon: "Icon (emoji)",
|
|
948
|
+
fieldColor: "Color",
|
|
933
949
|
fieldCustom: "Custom fields (key=value per line)",
|
|
934
950
|
error: "Something went wrong.",
|
|
935
951
|
kindLogin: "Login",
|
|
@@ -1008,6 +1024,8 @@ window.__ModuleLoader__.load({
|
|
|
1008
1024
|
fieldUrl: "URL",
|
|
1009
1025
|
fieldNotes: "备注",
|
|
1010
1026
|
fieldTags: "标签",
|
|
1027
|
+
fieldIcon: "图标(emoji)",
|
|
1028
|
+
fieldColor: "颜色",
|
|
1011
1029
|
fieldCustom: "自定义字段(每行 key=value)",
|
|
1012
1030
|
error: "操作失败。",
|
|
1013
1031
|
kindLogin: "登录",
|
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}\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 otpSecret?: string\n url?: string\n notes?: string\n tags?: 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 backupStatus: () => Promise<{ daysSinceBackup: number; backups: number }>\n health: () => Promise<{ weak: unknown[]; reused: unknown[] }>\n restore: (id: string) => Promise<{ restored: boolean }>\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 = Pick<\n VaultFullWire, 'title' | 'kind' | 'username' | 'email' | 'phone' | 'password' | 'host' | 'port'\n | 'privateKey' | 'apiKey' | 'secret' | 'accessToken' | 'refreshToken' | 'otpSecret' | 'url' | 'notes'\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]\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: '' }\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, history, stats, backupStatus, restore, 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 [codeMap, setCodeMap] = useState<Record<string, string>>({})\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[] } | null>(null)\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\n const readonly = policy?.accessMode === 'readonly'\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 /** 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 })\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 // 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 setCodeMap(previous => ({ ...previous, [id]: `${result.code} (${result.secondsRemaining}s)` }))\n } catch {\n setCodeMap(previous => ({ ...previous, [id]: t('error') }))\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 {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 <p className={css.reportLine}>{t('reportRotation')}: {report.rotation.length}</p>\n )}\n {report.weak.length > 0 && (\n <p className={css.reportLine}>{t('reportWeak')}: {report.weak.length}</p>\n )}\n {report.reused.length > 0 && (\n <p className={css.reportLine}>{t('reportReused')}: {report.reused.length}</p>\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 <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 {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 code = codeMap[entry.id]\n return (\n <li key={entry.id} className={css.row}>\n <div className={css.rowMain} onClick={() => setExpandedId(expandedId === entry.id ? null : entry.id)}>\n <span className={css.title}>\n <span className={css.kindIcon}>{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 </span>\n <span className={css.identity}>{identityLine(entry)}</span>\n {code !== undefined && <span className={css.totp}>{code}</span>}\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 <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 <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 ) : (\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 reportRotation: 'expired / due for rotation',\n reportWeak: 'weak passwords',\n reportReused: 'credentials reused across entries',\n showTrash: 'Trash',\n hideTrash: 'Hide trash',\n trashed: 'in trash',\n trashEmpty: 'Trash is empty',\n restore: 'Restore',\n clearTrash: 'Empty trash',\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 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 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 reportRotation: '已过期 / 待轮换',\n reportWeak: '弱密码',\n reportReused: '跨条目复用的凭据',\n showTrash: '回收站',\n hideTrash: '隐藏回收站',\n trashed: '已删除',\n trashEmpty: '回收站为空',\n restore: '恢复',\n clearTrash: '清空回收站',\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 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 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 backupStatus: () => invoke<{ daysSinceBackup: number; backups: number }>('backupStatus'),\n health: () => invoke<{ weak: unknown[]; reused: unknown[] }>('health'),\n restore: (id) => invoke<{ restored: boolean }>('restore', { id }),\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}\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 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 backupStatus: () => Promise<{ daysSinceBackup: number; backups: number }>\n health: () => Promise<{ weak: unknown[]; reused: unknown[] }>\n restore: (id: string) => Promise<{ restored: boolean }>\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 = Pick<\n VaultFullWire, 'title' | 'kind' | 'username' | 'email' | 'phone' | 'password' | 'host' | 'port'\n | 'privateKey' | 'apiKey' | 'secret' | 'accessToken' | 'refreshToken' | 'otpSecret' | 'url' | 'notes'\n | 'icon' | 'color'\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: '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, history, stats, backupStatus, restore, 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 [codeMap, setCodeMap] = useState<Record<string, string>>({})\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[] } | null>(null)\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\n const readonly = policy?.accessMode === 'readonly'\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 /** 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 })\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 // 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 setCodeMap(previous => ({ ...previous, [id]: `${result.code} (${result.secondsRemaining}s)` }))\n } catch {\n setCodeMap(previous => ({ ...previous, [id]: t('error') }))\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 {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 <p className={css.reportLine}>{t('reportRotation')}: {report.rotation.length}</p>\n )}\n {report.weak.length > 0 && (\n <p className={css.reportLine}>{t('reportWeak')}: {report.weak.length}</p>\n )}\n {report.reused.length > 0 && (\n <p className={css.reportLine}>{t('reportReused')}: {report.reused.length}</p>\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 <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 {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 code = codeMap[entry.id]\n return (\n <li key={entry.id} className={css.row}>\n <div className={css.rowMain} onClick={() => setExpandedId(expandedId === entry.id ? null : entry.id)}>\n <span className={css.title}>\n <span className={css.kindIcon}>{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 </span>\n <span className={css.identity}>{identityLine(entry)}</span>\n {code !== undefined && <span className={css.totp}>{code}</span>}\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 <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 <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 ) : (\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 reportRotation: 'expired / due for rotation',\n reportWeak: 'weak passwords',\n reportReused: 'credentials reused across entries',\n showTrash: 'Trash',\n hideTrash: 'Hide trash',\n trashed: 'in trash',\n trashEmpty: 'Trash is empty',\n restore: 'Restore',\n clearTrash: 'Empty trash',\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 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 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 reportRotation: '已过期 / 待轮换',\n reportWeak: '弱密码',\n reportReused: '跨条目复用的凭据',\n showTrash: '回收站',\n hideTrash: '隐藏回收站',\n trashed: '已删除',\n trashEmpty: '回收站为空',\n restore: '恢复',\n clearTrash: '清空回收站',\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 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 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 backupStatus: () => invoke<{ daysSinceBackup: number; backups: number }>('backupStatus'),\n health: () => invoke<{ weak: unknown[]; reused: unknown[] }>('health'),\n restore: (id) => invoke<{ restored: boolean }>('restore', { id }),\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
|
@@ -487,6 +487,7 @@ export async function apply(ctx, config) {
|
|
|
487
487
|
secret: { type: 'string', description: 'Bare Base32 secret or otpauth:// URI. Provide exactly one of id or secret.' },
|
|
488
488
|
period: { type: 'integer', description: 'Time step in seconds (default 30). Ignored when the secret is an otpauth URI that declares its own period.' },
|
|
489
489
|
digits: { type: 'integer', description: 'Code length (default 6; 6–10). Ignored when the secret is an otpauth URI that declares its own digits.' },
|
|
490
|
+
counter: { type: 'integer', description: 'HOTP counter (RFC 4226). When provided, generates a counter-based code instead of time-based TOTP.' },
|
|
490
491
|
},
|
|
491
492
|
output: {
|
|
492
493
|
schema: {
|
|
@@ -529,6 +530,14 @@ export async function apply(ctx, config) {
|
|
|
529
530
|
if (!Number.isInteger(digits) || digits < 6 || digits > 10) {
|
|
530
531
|
throw new Error('vault_totp: digits must be an integer 6–10');
|
|
531
532
|
}
|
|
533
|
+
if (args.counter !== undefined) {
|
|
534
|
+
if (!Number.isInteger(args.counter) || args.counter < 0) {
|
|
535
|
+
throw new Error('vault_totp: counter must be a non-negative integer');
|
|
536
|
+
}
|
|
537
|
+
const parsed = parseTotpSecret(secret);
|
|
538
|
+
const code = hotp(base32Decode(parsed.secret), args.counter, digits);
|
|
539
|
+
return { code, ...(label !== undefined ? { label } : {}), secondsRemaining: -1 };
|
|
540
|
+
}
|
|
532
541
|
const code = totpWith(secret, nowMs, period, digits);
|
|
533
542
|
const secondsRemaining = period - Math.floor(nowMs / 1000) % period;
|
|
534
543
|
return { code, ...(label !== undefined ? { label } : {}), secondsRemaining };
|
|
@@ -1407,6 +1416,59 @@ export async function apply(ctx, config) {
|
|
|
1407
1416
|
return { added, skipped };
|
|
1408
1417
|
},
|
|
1409
1418
|
}));
|
|
1419
|
+
// ── vault_autofill_check: does a target have usable credentials? ────────────
|
|
1420
|
+
ctx.tools.register(defineTool({
|
|
1421
|
+
name: 'vault_autofill_check',
|
|
1422
|
+
description: 'Check whether the vault has a credential usable for a URL/host: returns the best '
|
|
1423
|
+
+ 'matching entry (username/email only, never the secret) or a not-found verdict. Use before '
|
|
1424
|
+
+ 'deciding whether to autofill.',
|
|
1425
|
+
parameters: { target: { type: 'string', required: true, description: 'URL or host to match.' } },
|
|
1426
|
+
output: { schema: { type: 'object', additionalProperties: false, properties: { found: { type: 'boolean', required: true }, entry: { type: 'json' } } }, render: (_a, v) => [{ type: 'text', text: v.found ? `credentials available for ${v.entry?.title ?? 'entry'}` : 'no credentials for this target' }] },
|
|
1427
|
+
async execute(args) {
|
|
1428
|
+
const s = await guardStore();
|
|
1429
|
+
const target = args.target.trim().toLowerCase().replace(/^https?:\/\//, '').replace(/\/$/, '');
|
|
1430
|
+
if (target.length === 0)
|
|
1431
|
+
return { found: false };
|
|
1432
|
+
let best;
|
|
1433
|
+
for (const e of s.list()) {
|
|
1434
|
+
const host = (e.host ?? '').toLowerCase();
|
|
1435
|
+
const url = (e.url ?? '').toLowerCase();
|
|
1436
|
+
const hostBase = host.split(':')[0] ?? '';
|
|
1437
|
+
const matches = (host.length > 0 && host.includes(target))
|
|
1438
|
+
|| (url.length > 0 && url.includes(target))
|
|
1439
|
+
|| (hostBase.length > 0 && target.includes(hostBase));
|
|
1440
|
+
if (matches) {
|
|
1441
|
+
if (best === undefined || host.length > (best.host ?? '').length)
|
|
1442
|
+
best = e;
|
|
1443
|
+
}
|
|
1444
|
+
}
|
|
1445
|
+
if (best === undefined)
|
|
1446
|
+
return { found: false };
|
|
1447
|
+
const summary = { id: best.id, title: best.title, kind: best.kind ?? 'login' };
|
|
1448
|
+
const identity = best.username ?? best.email;
|
|
1449
|
+
if (identity !== undefined)
|
|
1450
|
+
summary.username = identity;
|
|
1451
|
+
return { found: true, entry: summary };
|
|
1452
|
+
},
|
|
1453
|
+
}));
|
|
1454
|
+
// ── vault_backup_now: explicit alias for an immediate backup ───────────────
|
|
1455
|
+
ctx.tools.register(defineTool({
|
|
1456
|
+
name: 'vault_backup_now',
|
|
1457
|
+
description: 'Create an immediate timestamped backup of the vault file (alias of vault_backup). '
|
|
1458
|
+
+ 'Returns the backup path.',
|
|
1459
|
+
parameters: {},
|
|
1460
|
+
output: { schema: { type: 'object', additionalProperties: false, properties: { path: { type: 'string', required: true } } }, render: (_a, v) => [{ type: 'text', text: `backup written to ${v.path}` }] },
|
|
1461
|
+
async execute() {
|
|
1462
|
+
const s = await guardStore();
|
|
1463
|
+
const source = resolveVaultPath(config);
|
|
1464
|
+
const backup = join(dirname(source), `vault-backup-${Date.now()}.json`);
|
|
1465
|
+
const raw = await readFile(source, 'utf8');
|
|
1466
|
+
await mkdir(dirname(backup), { recursive: true, mode: 0o700 });
|
|
1467
|
+
await writeFile(backup, raw, { mode: 0o600 });
|
|
1468
|
+
void s;
|
|
1469
|
+
return { path: backup };
|
|
1470
|
+
},
|
|
1471
|
+
}));
|
|
1410
1472
|
// ── vault_rotation: expiry / rotation report ───────────────────────────────
|
|
1411
1473
|
ctx.tools.register(defineTool({
|
|
1412
1474
|
name: 'vault_rotation',
|
|
@@ -1714,7 +1776,12 @@ export async function apply(ctx, config) {
|
|
|
1714
1776
|
record.favorite = record.favorite.toLowerCase() === 'true';
|
|
1715
1777
|
for (const numKey of ['expiresAt', 'rotationDays']) {
|
|
1716
1778
|
if (typeof record[numKey] === 'string' && /^-?\d+$/.test(record[numKey])) {
|
|
1717
|
-
|
|
1779
|
+
const parsed = Number(record[numKey]);
|
|
1780
|
+
if (!Number.isSafeInteger(parsed)) {
|
|
1781
|
+
skipped++;
|
|
1782
|
+
continue;
|
|
1783
|
+
}
|
|
1784
|
+
record[numKey] = parsed;
|
|
1718
1785
|
}
|
|
1719
1786
|
}
|
|
1720
1787
|
if (Object.keys(fields).length > 0)
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dsh-vault",
|
|
3
|
-
"version": "0.8.
|
|
3
|
+
"version": "0.8.2",
|
|
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",
|