@ai-matrx/vault 0.1.19 → 0.1.20
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/CHANGELOG.md +26 -2
- package/dist/index.cjs +158 -75
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +30 -5
- package/dist/index.d.ts +30 -5
- package/dist/index.js +179 -96
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -671,7 +671,7 @@ var DAY_FORMAT = { year: "numeric", month: "short", day: "numeric" };
|
|
|
671
671
|
import { Fragment as Fragment2, jsx as jsx5, jsxs as jsxs5 } from "react/jsx-runtime";
|
|
672
672
|
var MASK = "\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022";
|
|
673
673
|
function SecretText({ value, multiline }) {
|
|
674
|
-
if (multiline || value.length > 200) return /* @__PURE__ */ jsx5("span", { className: "whitespace-pre-wrap break-all font-mono text-sm", children: value });
|
|
674
|
+
if (multiline || value.length > 200 || value.includes("\n")) return /* @__PURE__ */ jsx5("span", { className: "whitespace-pre-wrap break-all font-mono text-sm", children: value });
|
|
675
675
|
return /* @__PURE__ */ jsx5("span", { className: "break-all font-mono text-sm tracking-wide", children: [...value].map((ch, i) => /* @__PURE__ */ jsx5("span", { className: /[0-9]/.test(ch) ? "text-primary" : /[^A-Za-z0-9]/.test(ch) ? "text-warning" : void 0, children: ch }, i)) });
|
|
676
676
|
}
|
|
677
677
|
var quietError = (e, fallback) => wasCancelled(e) ? null : e instanceof Error ? e.message : fallback;
|
|
@@ -807,18 +807,19 @@ function EditRow({ label, hint: hint2, value, onChange, placeholder, secret = fa
|
|
|
807
807
|
}
|
|
808
808
|
);
|
|
809
809
|
}
|
|
810
|
-
function CustomEditRow({ label, value, onLabel, onValue, secret, onRemove, extra, onPasteValue }) {
|
|
810
|
+
function CustomEditRow({ label, value, onLabel, onValue, secret, onRemove, extra, onPasteValue, multiline = false }) {
|
|
811
811
|
const [shown, setShown] = useState5(false);
|
|
812
812
|
return /* @__PURE__ */ jsx5(
|
|
813
813
|
VaultRow,
|
|
814
814
|
{
|
|
815
815
|
label: /* @__PURE__ */ jsx5(Field2, { className: "w-full", value: label, onChange: (e) => onLabel(e.target.value), placeholder: "Name", "aria-label": "Field name" }),
|
|
816
|
+
top: multiline,
|
|
816
817
|
actions: /* @__PURE__ */ jsxs5(Fragment2, { children: [
|
|
817
|
-
secret && value ? /* @__PURE__ */ jsx5(Button2, { variant: "quiet", icon: shown ? /* @__PURE__ */ jsx5(EyeOffGlyph, {}) : /* @__PURE__ */ jsx5(EyeGlyph, {}), "aria-label": shown ? "Hide" : "Show", onClick: () => setShown((x) => !x) }) : null,
|
|
818
|
+
secret && value && !multiline ? /* @__PURE__ */ jsx5(Button2, { variant: "quiet", icon: shown ? /* @__PURE__ */ jsx5(EyeOffGlyph, {}) : /* @__PURE__ */ jsx5(EyeGlyph, {}), "aria-label": shown ? "Hide" : "Show", onClick: () => setShown((x) => !x) }) : null,
|
|
818
819
|
extra,
|
|
819
820
|
/* @__PURE__ */ jsx5(Button2, { variant: "quiet", removes: true, icon: /* @__PURE__ */ jsx5(XGlyph, {}), "aria-label": "Remove field", onClick: onRemove })
|
|
820
821
|
] }),
|
|
821
|
-
children: /* @__PURE__ */ jsx5(
|
|
822
|
+
children: multiline ? /* @__PURE__ */ jsx5(Textarea, { className: "w-full", value, onChange: (e) => onValue(e.target.value), rows: 4, placeholder: secret ? "Encrypted, hidden until shown" : "Value", autoComplete: "off", spellCheck: !secret, "aria-label": label ? `${label} value` : "Field value" }) : /* @__PURE__ */ jsx5(
|
|
822
823
|
Field2,
|
|
823
824
|
{
|
|
824
825
|
className: "w-full",
|
|
@@ -937,6 +938,7 @@ function sortItems(items, sort, recents) {
|
|
|
937
938
|
if (sort === "updated") return out.sort((a, b) => b.updatedAt.localeCompare(a.updatedAt));
|
|
938
939
|
return out.sort((a, b) => b.createdAt.localeCompare(a.createdAt));
|
|
939
940
|
}
|
|
941
|
+
var SECURE_NOTE_KEY = "secure_notes";
|
|
940
942
|
function draftOf(item) {
|
|
941
943
|
return {
|
|
942
944
|
name: item?.name ?? "",
|
|
@@ -987,7 +989,9 @@ function rebaseDraft(oldBase, newBase, draft) {
|
|
|
987
989
|
secrets: draft.secrets,
|
|
988
990
|
custom,
|
|
989
991
|
removed: draft.removed,
|
|
990
|
-
authenticator: draft.authenticator
|
|
992
|
+
authenticator: draft.authenticator,
|
|
993
|
+
...draft.browser ? { browser: draft.browser } : {},
|
|
994
|
+
...draft.fieldSettings ? { fieldSettings: draft.fieldSettings } : {}
|
|
991
995
|
};
|
|
992
996
|
}
|
|
993
997
|
function panesShown(mode, specialView, showingDetail) {
|
|
@@ -1015,7 +1019,8 @@ var FAMILY_LABELS = {
|
|
|
1015
1019
|
signing_files: "Signing & files"
|
|
1016
1020
|
};
|
|
1017
1021
|
var COMMON_DEFINITION_KEYS = ["website_login", "username_password", "api_key", "env_value", "database_login", "custom"];
|
|
1018
|
-
var MULTILINE = /(json|pem|private_key|certificate|cert|bundle|document|recovery_codes)/;
|
|
1022
|
+
var MULTILINE = /(json|pem|private_key|certificate|cert|bundle|document|recovery_codes|(^|_)notes?($|_))/;
|
|
1023
|
+
var isMultilineKey = (key) => MULTILINE.test(key);
|
|
1019
1024
|
var SECRET = /(password|secret|token|api_key|private|passphrase|credential|seed|key$|_key)/;
|
|
1020
1025
|
var URLISH = /(url|uri|endpoint|webhook|hook)/;
|
|
1021
1026
|
function humanize(key) {
|
|
@@ -2229,7 +2234,7 @@ function normalizeWebsite(raw) {
|
|
|
2229
2234
|
return null;
|
|
2230
2235
|
}
|
|
2231
2236
|
}
|
|
2232
|
-
function AddOtpPanel({ port, items, definitions, itemId = null, onClose, onChanged, onDone }) {
|
|
2237
|
+
function AddOtpPanel({ port, items, definitions, itemId = null, onClose, onChanged, onAdded, onDone }) {
|
|
2233
2238
|
const confirmed = useConfirmed();
|
|
2234
2239
|
const candidates = items.filter((i) => !i.authenticator && !i.deletion && (i.capabilities.canEdit || i.capabilities.canManage)).sort((a, b) => a.name.localeCompare(b.name, void 0, { sensitivity: "base" }));
|
|
2235
2240
|
const [input, setInput] = useState12("");
|
|
@@ -2282,6 +2287,7 @@ function AddOtpPanel({ port, items, definitions, itemId = null, onClose, onChang
|
|
|
2282
2287
|
setInput("");
|
|
2283
2288
|
setImage(null);
|
|
2284
2289
|
setSaved(next);
|
|
2290
|
+
onAdded?.(next);
|
|
2285
2291
|
onChanged();
|
|
2286
2292
|
} catch (e) {
|
|
2287
2293
|
setError(wasCancelled(e) ? "Not confirmed, so nothing was added." : otpActionError(e, "add it"));
|
|
@@ -2390,7 +2396,23 @@ function otpGroups(items, entries, query, hidden = /* @__PURE__ */ new Set()) {
|
|
|
2390
2396
|
const rank = (k) => k === "me" ? 0 : k === "shared" ? 2 : 1;
|
|
2391
2397
|
return [...groups.entries()].sort(([a, x], [b, y]) => rank(a) - rank(b) || x.label.localeCompare(y.label)).map(([key, g]) => ({ key, ...g }));
|
|
2392
2398
|
}
|
|
2393
|
-
function
|
|
2399
|
+
function withAdded(items, added) {
|
|
2400
|
+
if (added.size === 0) return items;
|
|
2401
|
+
const seen = /* @__PURE__ */ new Set();
|
|
2402
|
+
const out = items.map((i) => {
|
|
2403
|
+
seen.add(i.id);
|
|
2404
|
+
const mine = added.get(i.id);
|
|
2405
|
+
return mine && !i.authenticator ? { ...i, authenticator: mine.authenticator, name: mine.name } : i;
|
|
2406
|
+
});
|
|
2407
|
+
for (const [id, a] of added) if (!seen.has(id)) out.push(a);
|
|
2408
|
+
return out;
|
|
2409
|
+
}
|
|
2410
|
+
function AuthenticatorView({ port, host, items: listed, definitions, query, onOpen, onChanged, header }) {
|
|
2411
|
+
const [added, setAdded] = useState13(/* @__PURE__ */ new Map());
|
|
2412
|
+
const items = withAdded(listed, added);
|
|
2413
|
+
useEffect11(() => {
|
|
2414
|
+
if (added.size > 0 && [...added.keys()].every((id) => listed.some((i) => i.id === id && i.authenticator))) setAdded(/* @__PURE__ */ new Map());
|
|
2415
|
+
}, [listed, added]);
|
|
2394
2416
|
const [entries, setEntries] = useState13(/* @__PURE__ */ new Map());
|
|
2395
2417
|
const [hidden, setHidden] = useState13(/* @__PURE__ */ new Set());
|
|
2396
2418
|
const [adding, setAdding] = useState13(false);
|
|
@@ -2406,7 +2428,7 @@ function AuthenticatorView({ port, host, items, definitions, query, onOpen, onCh
|
|
|
2406
2428
|
return () => {
|
|
2407
2429
|
live = false;
|
|
2408
2430
|
};
|
|
2409
|
-
}, [port,
|
|
2431
|
+
}, [port, listed, added]);
|
|
2410
2432
|
const groups = otpGroups(items, entries, query, hidden);
|
|
2411
2433
|
const total = items.filter((i) => i.authenticator && !i.deletion && !hidden.has(i.id)).length;
|
|
2412
2434
|
const familyOf2 = (key) => definitions.find((d) => d.key === key)?.family ?? "generic";
|
|
@@ -2452,6 +2474,7 @@ function AuthenticatorView({ port, host, items, definitions, query, onOpen, onCh
|
|
|
2452
2474
|
definitions,
|
|
2453
2475
|
onClose: () => setAdding(false),
|
|
2454
2476
|
onChanged,
|
|
2477
|
+
onAdded: (item) => setAdded((cur) => new Map(cur).set(item.id, item)),
|
|
2455
2478
|
onDone: (id) => {
|
|
2456
2479
|
setAdding(false);
|
|
2457
2480
|
onOpen(id);
|
|
@@ -4797,7 +4820,7 @@ import { Button as Button23, SearchField } from "@ai-matrx/design-system/control
|
|
|
4797
4820
|
import { CopyIcon as CopyIcon7 } from "@ai-matrx/design-system/icons";
|
|
4798
4821
|
|
|
4799
4822
|
// src/ItemPane.tsx
|
|
4800
|
-
import { useEffect as useEffect16, useMemo as useMemo3, useRef as useRef14, useState as useState27 } from "react";
|
|
4823
|
+
import { Fragment as Fragment17, useEffect as useEffect16, useMemo as useMemo3, useRef as useRef14, useState as useState27 } from "react";
|
|
4801
4824
|
import { DropdownMenu as DropdownMenu3, DropdownMenuContent as DropdownMenuContent3, DropdownMenuItem as DropdownMenuItem3, DropdownMenuSeparator as DropdownMenuSeparator3, DropdownMenuTrigger as DropdownMenuTrigger3 } from "@ai-matrx/design-system";
|
|
4802
4825
|
import { cn as cn12 } from "@ai-matrx/design-system";
|
|
4803
4826
|
import { Badge as Badge7, Button as Button22, CONTROLS_CONTAINER_CLASS, OptionCombobox, Switch as Switch6 } from "@ai-matrx/design-system/controls";
|
|
@@ -5179,14 +5202,12 @@ import { confirm as confirm7 } from "@ai-matrx/kit/confirm-opener";
|
|
|
5179
5202
|
import { Fragment as Fragment15, jsx as jsx22, jsxs as jsxs21 } from "react/jsx-runtime";
|
|
5180
5203
|
var HANDLINGS = ["visible", "revealable", "sealed"];
|
|
5181
5204
|
var hint = (text, tone = "muted") => /* @__PURE__ */ jsx22("span", { className: tone === "destructive" ? "text-destructive" : void 0, title: text, children: text });
|
|
5182
|
-
var
|
|
5183
|
-
function
|
|
5184
|
-
const
|
|
5185
|
-
const env = field.envKey ?? "";
|
|
5205
|
+
var saysMore = (s, defaultHandling) => Boolean(s.envKey?.trim() || s.injectIntoSandbox || s.handling && s.handling !== defaultHandling);
|
|
5206
|
+
function FieldSettingsRows({ name, value, defaultHandling = "revealable", onChange }) {
|
|
5207
|
+
const env = value.envKey ?? "";
|
|
5186
5208
|
const envProblem = envKeyProblem(env);
|
|
5187
5209
|
const envOk = env.trim() !== "" && !envProblem;
|
|
5188
|
-
const handling =
|
|
5189
|
-
const name = field.label.trim() || "Secret";
|
|
5210
|
+
const handling = value.handling ?? defaultHandling;
|
|
5190
5211
|
const chooseHandling = async (next) => {
|
|
5191
5212
|
if (next === handling) return;
|
|
5192
5213
|
if (next === "sealed") {
|
|
@@ -5200,6 +5221,38 @@ function SecretBuilderRow({ field, onChange, onRemove }) {
|
|
|
5200
5221
|
}
|
|
5201
5222
|
onChange({ handling: next });
|
|
5202
5223
|
};
|
|
5224
|
+
return /* @__PURE__ */ jsxs21(Fragment15, { children: [
|
|
5225
|
+
/* @__PURE__ */ jsx22(VaultRow, { label: "Env key", hint: envProblem ? hint(envProblem, "destructive") : hint("The name sandboxes and workflows use"), children: /* @__PURE__ */ jsx22(
|
|
5226
|
+
Field8,
|
|
5227
|
+
{
|
|
5228
|
+
className: "w-full font-mono",
|
|
5229
|
+
"aria-label": `${name} env key`,
|
|
5230
|
+
"aria-invalid": Boolean(envProblem),
|
|
5231
|
+
placeholder: "e.g. GITHUB_TOKEN",
|
|
5232
|
+
autoComplete: "off",
|
|
5233
|
+
spellCheck: false,
|
|
5234
|
+
value: env,
|
|
5235
|
+
onChange: (e) => onChange({ envKey: e.target.value, ...e.target.value.trim() ? {} : { injectIntoSandbox: false } })
|
|
5236
|
+
}
|
|
5237
|
+
) }),
|
|
5238
|
+
/* @__PURE__ */ jsx22(VaultRow, { label: "Who can see it", hint: hint(HANDLING_WORDS[handling].hint), children: /* @__PURE__ */ jsx22(
|
|
5239
|
+
SegmentedControl5,
|
|
5240
|
+
{
|
|
5241
|
+
"aria-label": `Who can see ${name}`,
|
|
5242
|
+
value: handling,
|
|
5243
|
+
onValueChange: (v) => void chooseHandling(v),
|
|
5244
|
+
data: HANDLINGS.map((h) => ({ value: h, label: HANDLING_WORDS[h].label, title: HANDLING_WORDS[h].hint }))
|
|
5245
|
+
}
|
|
5246
|
+
) }),
|
|
5247
|
+
/* @__PURE__ */ jsx22(VaultRow, { label: "Use in sandbox", hint: envOk ? hint("Sandboxes get it as an env variable") : hint("Needs an env key"), children: /* @__PURE__ */ jsx22(Switch5, { "aria-label": `Use ${name} in sandbox`, checked: envOk && value.injectIntoSandbox === true, disabled: !envOk, onCheckedChange: (v) => onChange({ injectIntoSandbox: v }) }) })
|
|
5248
|
+
] });
|
|
5249
|
+
}
|
|
5250
|
+
var hasSecretSettings = (s) => saysMore(s, "revealable");
|
|
5251
|
+
var hasDeclaredSettings = (s, defaultHandling) => Boolean(s && saysMore(s, defaultHandling));
|
|
5252
|
+
function SecretBuilderRow({ field, onChange, onRemove }) {
|
|
5253
|
+
const [open, setOpen] = useState22(hasSecretSettings(field));
|
|
5254
|
+
const handling = field.handling ?? "revealable";
|
|
5255
|
+
const name = field.label.trim() || "Secret";
|
|
5203
5256
|
return /* @__PURE__ */ jsxs21(Fragment15, { children: [
|
|
5204
5257
|
/* @__PURE__ */ jsx22(
|
|
5205
5258
|
CustomEditRow,
|
|
@@ -5207,47 +5260,26 @@ function SecretBuilderRow({ field, onChange, onRemove }) {
|
|
|
5207
5260
|
label: field.label,
|
|
5208
5261
|
value: field.value,
|
|
5209
5262
|
secret: true,
|
|
5263
|
+
multiline: field.multiline === true,
|
|
5210
5264
|
onLabel: (v) => onChange({ label: v }),
|
|
5211
5265
|
onValue: (v) => onChange({ value: v }),
|
|
5212
5266
|
onRemove,
|
|
5213
|
-
|
|
5214
|
-
|
|
5215
|
-
|
|
5216
|
-
|
|
5217
|
-
|
|
5218
|
-
|
|
5267
|
+
...field.multiline ? {} : {
|
|
5268
|
+
onPasteValue: (text) => {
|
|
5269
|
+
const a = parseEnvAssignment(text);
|
|
5270
|
+
if (!a) return false;
|
|
5271
|
+
onChange({ envKey: a.key, value: a.value, ...field.label.trim() ? {} : { label: labelFromEnvKey(a.key) } });
|
|
5272
|
+
setOpen(true);
|
|
5273
|
+
return true;
|
|
5274
|
+
}
|
|
5219
5275
|
},
|
|
5220
5276
|
extra: /* @__PURE__ */ jsxs21(Fragment15, { children: [
|
|
5221
|
-
handling !== "sealed" ? /* @__PURE__ */ jsx22(GenerateButton, { onUse: (v) => onChange({ value: v }) }) : null,
|
|
5277
|
+
handling !== "sealed" && !field.multiline ? /* @__PURE__ */ jsx22(GenerateButton, { onUse: (v) => onChange({ value: v }) }) : null,
|
|
5222
5278
|
/* @__PURE__ */ jsx22(Button18, { variant: "quiet", icon: /* @__PURE__ */ jsx22(SlidersGlyph, {}), "aria-label": `${name} settings`, pressed: open, onClick: () => setOpen((o) => !o) })
|
|
5223
5279
|
] })
|
|
5224
5280
|
}
|
|
5225
5281
|
),
|
|
5226
|
-
open ? /* @__PURE__ */
|
|
5227
|
-
/* @__PURE__ */ jsx22(VaultRow, { label: "Env key", hint: envProblem ? hint(envProblem, "destructive") : hint("The name sandboxes and workflows use"), children: /* @__PURE__ */ jsx22(
|
|
5228
|
-
Field8,
|
|
5229
|
-
{
|
|
5230
|
-
className: "w-full font-mono",
|
|
5231
|
-
"aria-label": `${name} env key`,
|
|
5232
|
-
"aria-invalid": Boolean(envProblem),
|
|
5233
|
-
placeholder: "e.g. GITHUB_TOKEN",
|
|
5234
|
-
autoComplete: "off",
|
|
5235
|
-
spellCheck: false,
|
|
5236
|
-
value: env,
|
|
5237
|
-
onChange: (e) => onChange({ envKey: e.target.value, ...e.target.value.trim() ? {} : { injectIntoSandbox: false } })
|
|
5238
|
-
}
|
|
5239
|
-
) }),
|
|
5240
|
-
/* @__PURE__ */ jsx22(VaultRow, { label: "Who can see it", hint: hint(HANDLING_WORDS[handling].hint), children: /* @__PURE__ */ jsx22(
|
|
5241
|
-
SegmentedControl5,
|
|
5242
|
-
{
|
|
5243
|
-
"aria-label": `Who can see ${name}`,
|
|
5244
|
-
value: handling,
|
|
5245
|
-
onValueChange: (v) => void chooseHandling(v),
|
|
5246
|
-
data: HANDLINGS.map((h) => ({ value: h, label: HANDLING_WORDS[h].label, title: HANDLING_WORDS[h].hint }))
|
|
5247
|
-
}
|
|
5248
|
-
) }),
|
|
5249
|
-
/* @__PURE__ */ jsx22(VaultRow, { label: "Use in sandbox", hint: envOk ? hint("Sandboxes get it as an env variable") : hint("Needs an env key"), children: /* @__PURE__ */ jsx22(Switch5, { "aria-label": `Use ${name} in sandbox`, checked: envOk && field.injectIntoSandbox === true, disabled: !envOk, onCheckedChange: (v) => onChange({ injectIntoSandbox: v }) }) })
|
|
5250
|
-
] }) : null
|
|
5282
|
+
open ? /* @__PURE__ */ jsx22(FieldSettingsRows, { name, value: field, onChange }) : null
|
|
5251
5283
|
] });
|
|
5252
5284
|
}
|
|
5253
5285
|
function withMfaMethod(custom, v) {
|
|
@@ -5876,7 +5908,9 @@ function SharingSummary({ item, port, className }) {
|
|
|
5876
5908
|
|
|
5877
5909
|
// src/ItemPane.tsx
|
|
5878
5910
|
import { formatAbsoluteDate as formatAbsoluteDate3 } from "@ai-matrx/kit/format";
|
|
5879
|
-
import { Fragment as
|
|
5911
|
+
import { Fragment as Fragment18, jsx as jsx27, jsxs as jsxs25 } from "react/jsx-runtime";
|
|
5912
|
+
var ENV_VALUE_KEY = "env_value";
|
|
5913
|
+
var secureNoteDraft = () => ({ key: SECURE_NOTE_KEY, label: "Secure note", value: "", multiline: true, description: "Encrypted notes" });
|
|
5880
5914
|
var USERNAME_KEYS = /^(username|user_name|email|login|username_or_email|account_email)$/;
|
|
5881
5915
|
function ItemPane(props) {
|
|
5882
5916
|
const { port, item, definition, mode, host, organizations, defaultOwner, seed, onBack, onMode, onSaved, onDeleted, onDirty, onCancelNew, onPanel, onChanged, favorite, notice, refreshKey } = props;
|
|
@@ -6067,6 +6101,16 @@ function ItemPane(props) {
|
|
|
6067
6101
|
const fieldSettings = (f) => canEdit ? /* @__PURE__ */ jsx27(Button22, { variant: "quiet", icon: /* @__PURE__ */ jsx27(SlidersGlyph, {}), "aria-label": `${f.label} settings`, title: `${f.label} settings`, onClick: () => onPanel(`field:${f.id}`) }) : null;
|
|
6068
6102
|
const turnOnOne = canTurnOn ? (f) => () => turnOn([f]) : () => void 0;
|
|
6069
6103
|
const declaredKeys = new Set(declared.map((f) => f.key));
|
|
6104
|
+
const hasSecureNote = declaredKeys.has(SECURE_NOTE_KEY) || Boolean(item?.fields.some((f) => f.key === SECURE_NOTE_KEY)) || draft.secrets.some((x) => x.key === SECURE_NOTE_KEY);
|
|
6105
|
+
const [settingsToggled, setSettingsToggled] = useState27(/* @__PURE__ */ new Set());
|
|
6106
|
+
const settingsOpen = (f) => settingsToggled.has(f.key) !== (definition?.key === ENV_VALUE_KEY || hasDeclaredSettings(draft.fieldSettings?.[f.key], f.handling));
|
|
6107
|
+
const toggleSettings = (key) => setSettingsToggled((cur) => {
|
|
6108
|
+
const next = new Set(cur);
|
|
6109
|
+
if (next.has(key)) next.delete(key);
|
|
6110
|
+
else next.add(key);
|
|
6111
|
+
return next;
|
|
6112
|
+
});
|
|
6113
|
+
const patchFieldSettings = (key, p) => setDraft((d) => ({ ...d, fieldSettings: { ...d.fieldSettings, [key]: { ...d.fieldSettings?.[key], ...p } } }));
|
|
6070
6114
|
const extraFields = (item?.fields ?? []).filter((f) => !declaredKeys.has(f.key) && !draft.removed.includes(f.id) && !isAuthenticatorStorage(f.key));
|
|
6071
6115
|
const metaValue = (key) => draft.values[key] ?? item?.custom.find((c) => c.key === key)?.value ?? "";
|
|
6072
6116
|
const extraCustom = draft.custom.filter((c) => !declaredKeys.has(c.key) && c.key !== MFA_METHOD_KEY && !isAuthenticatorStorage(c.key));
|
|
@@ -6149,7 +6193,7 @@ function ItemPane(props) {
|
|
|
6149
6193
|
/* @__PURE__ */ jsx27(SettingsIcon, { className: "size-4" }),
|
|
6150
6194
|
"Settings"
|
|
6151
6195
|
] }) : null,
|
|
6152
|
-
canManage ? /* @__PURE__ */ jsxs25(
|
|
6196
|
+
canManage ? /* @__PURE__ */ jsxs25(Fragment18, { children: [
|
|
6153
6197
|
/* @__PURE__ */ jsx27(DropdownMenuSeparator3, {}),
|
|
6154
6198
|
/* @__PURE__ */ jsxs25(DropdownMenuItem3, { className: "text-destructive", disabled: busy, onSelect: () => void remove(), children: [
|
|
6155
6199
|
/* @__PURE__ */ jsx27(TrashGlyph, { className: "size-4" }),
|
|
@@ -6169,7 +6213,7 @@ function ItemPane(props) {
|
|
|
6169
6213
|
/* @__PURE__ */ jsx27("span", { className: "min-w-0 flex-1 truncate text-warning", children: offFields.length === 0 ? "This item is turned off" : offFields.length === 1 ? "1 field is turned off" : `${offFields.length} fields are turned off` }),
|
|
6170
6214
|
canTurnOn ? /* @__PURE__ */ jsx27(TurnOnButton, { label: "all fields", onTurnOn: () => turnOn(offFields) }) : null
|
|
6171
6215
|
] }) : null,
|
|
6172
|
-
/* @__PURE__ */ jsx27("div", { className: "min-h-0 flex-1 overflow-y-auto", children: sent ? /* @__PURE__ */ jsx27(AssignResult, { sent, onAnother: createAnother, onDone: onCancelNew }) : /* @__PURE__ */ jsx27("div", { className: "mx-auto flex w-full max-w-3xl flex-col gap-5 px-3 py-4 sm:px-6 sm:py-6", children: editing ? /* @__PURE__ */ jsxs25(
|
|
6216
|
+
/* @__PURE__ */ jsx27("div", { className: "min-h-0 flex-1 overflow-y-auto", children: sent ? /* @__PURE__ */ jsx27(AssignResult, { sent, onAnother: createAnother, onDone: onCancelNew }) : /* @__PURE__ */ jsx27("div", { className: "mx-auto flex w-full max-w-3xl flex-col gap-5 px-3 py-4 sm:px-6 sm:py-6", children: editing ? /* @__PURE__ */ jsxs25(Fragment18, { children: [
|
|
6173
6217
|
/* @__PURE__ */ jsxs25(VaultSection, { children: [
|
|
6174
6218
|
mode === "new" ? /* @__PURE__ */ jsx27(VaultRow, { label: "Save to", children: /* @__PURE__ */ jsx27(
|
|
6175
6219
|
OptionCombobox,
|
|
@@ -6190,7 +6234,7 @@ function ItemPane(props) {
|
|
|
6190
6234
|
}
|
|
6191
6235
|
) }) : null,
|
|
6192
6236
|
/* @__PURE__ */ jsx27(EditRow, { label: "Name", value: draft.name, onChange: (v) => patch({ name: v }), placeholder: "Name", autoFocus: mode === "new" }),
|
|
6193
|
-
mode === "new" && owner === "person" ? /* @__PURE__ */ jsxs25(
|
|
6237
|
+
mode === "new" && owner === "person" ? /* @__PURE__ */ jsxs25(Fragment18, { children: [
|
|
6194
6238
|
/* @__PURE__ */ jsx27(EditRow, { label: "Their email", value: recipient, placeholder: "name@company.com", inputMode: "email", onChange: setRecipient }),
|
|
6195
6239
|
declared.some((f) => f.storage === "encrypted" && f.kind === "secret") ? /* @__PURE__ */ jsx27(VaultRow, { label: "Password", hint: "You never see it", children: /* @__PURE__ */ jsx27(Switch6, { checked: generatePrivately, onCheckedChange: setGeneratePrivately, "aria-label": "Generate the password privately" }) }) : null
|
|
6196
6240
|
] }) : null,
|
|
@@ -6199,24 +6243,29 @@ function ItemPane(props) {
|
|
|
6199
6243
|
const secretKind = f.storage === "encrypted" && f.kind === "secret";
|
|
6200
6244
|
const value = f.storage === "metadata" ? metaValue(f.key) : draft.values[f.key] ?? "";
|
|
6201
6245
|
const hidden = existing && existing.handling !== "visible" && !(f.key in loaded);
|
|
6202
|
-
|
|
6203
|
-
|
|
6204
|
-
|
|
6205
|
-
|
|
6206
|
-
|
|
6207
|
-
|
|
6208
|
-
|
|
6209
|
-
|
|
6210
|
-
|
|
6211
|
-
|
|
6212
|
-
|
|
6213
|
-
|
|
6214
|
-
|
|
6215
|
-
|
|
6216
|
-
|
|
6217
|
-
|
|
6218
|
-
|
|
6219
|
-
|
|
6246
|
+
const newSecret = mode === "new" && f.storage === "encrypted" && owner !== "person";
|
|
6247
|
+
const open = newSecret && settingsOpen(f);
|
|
6248
|
+
return /* @__PURE__ */ jsxs25(Fragment17, { children: [
|
|
6249
|
+
/* @__PURE__ */ jsx27(
|
|
6250
|
+
EditRow,
|
|
6251
|
+
{
|
|
6252
|
+
label: f.label,
|
|
6253
|
+
value,
|
|
6254
|
+
placeholder: hidden ? "\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022" : f.required ? "Required" : isRecoveryCodesField(f) ? "Backup codes, one per line" : "",
|
|
6255
|
+
secret: secretKind,
|
|
6256
|
+
multiline: f.kind === "multiline" || value.includes("\n"),
|
|
6257
|
+
inputMode: f.kind === "url" ? "url" : USERNAME_KEYS.test(f.key) ? "email" : "text",
|
|
6258
|
+
onChange: (v) => setValue(f.key, v),
|
|
6259
|
+
actions: /* @__PURE__ */ jsxs25(Fragment18, { children: [
|
|
6260
|
+
hidden && existing?.handling === "revealable" && item?.capabilities.canReveal ? /* @__PURE__ */ jsx27(Button22, { variant: "quiet", icon: /* @__PURE__ */ jsx27(EyeGlyph, {}), "aria-label": `Show current ${f.label}`, onClick: () => void loadForEdit(f.key) }) : null,
|
|
6261
|
+
secretKind ? /* @__PURE__ */ jsx27(GenerateButton, { onUse: (v) => setValue(f.key, v) }) : null,
|
|
6262
|
+
existing ? /* @__PURE__ */ jsx27(Button22, { variant: "quiet", icon: /* @__PURE__ */ jsx27(SettingsIcon, {}), "aria-label": `${f.label} settings`, onClick: () => onPanel(`field:${existing.id}`) }) : null,
|
|
6263
|
+
newSecret ? /* @__PURE__ */ jsx27(Button22, { variant: "quiet", icon: /* @__PURE__ */ jsx27(SlidersGlyph, {}), "aria-label": `${f.label} settings`, pressed: open, onClick: () => toggleSettings(f.key) }) : null
|
|
6264
|
+
] })
|
|
6265
|
+
}
|
|
6266
|
+
),
|
|
6267
|
+
open ? /* @__PURE__ */ jsx27(FieldSettingsRows, { name: f.label, value: draft.fieldSettings?.[f.key] ?? {}, defaultHandling: f.handling, onChange: (p) => patchFieldSettings(f.key, p) }) : null
|
|
6268
|
+
] }, f.key);
|
|
6220
6269
|
}),
|
|
6221
6270
|
extraFields.map((f) => /* @__PURE__ */ jsx27(
|
|
6222
6271
|
EditRow,
|
|
@@ -6225,11 +6274,11 @@ function ItemPane(props) {
|
|
|
6225
6274
|
value: draft.values[f.key] ?? "",
|
|
6226
6275
|
placeholder: f.handling === "visible" || f.key in loaded ? "" : "\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022",
|
|
6227
6276
|
secret: f.handling !== "visible" && !isRecoveryCodesField(f),
|
|
6228
|
-
multiline: isRecoveryCodesField(f),
|
|
6277
|
+
multiline: f.kind === "multiline" || isRecoveryCodesField(f) || (draft.values[f.key] ?? "").includes("\n"),
|
|
6229
6278
|
onChange: (v) => setValue(f.key, v),
|
|
6230
6279
|
onRemove: () => patch({ removed: [...draft.removed, f.id] }),
|
|
6231
6280
|
removeLabel: `Delete ${f.label}`,
|
|
6232
|
-
actions: /* @__PURE__ */ jsxs25(
|
|
6281
|
+
actions: /* @__PURE__ */ jsxs25(Fragment18, { children: [
|
|
6233
6282
|
f.handling === "revealable" && !(f.key in loaded) && item?.capabilities.canReveal ? /* @__PURE__ */ jsx27(Button22, { variant: "quiet", icon: /* @__PURE__ */ jsx27(EyeGlyph, {}), "aria-label": `Show current ${f.label}`, onClick: () => void loadForEdit(f.key) }) : null,
|
|
6234
6283
|
/* @__PURE__ */ jsx27(Button22, { variant: "quiet", icon: /* @__PURE__ */ jsx27(SettingsIcon, {}), "aria-label": `${f.label} settings`, onClick: () => onPanel(`field:${f.id}`) })
|
|
6235
6284
|
] })
|
|
@@ -6294,6 +6343,7 @@ function ItemPane(props) {
|
|
|
6294
6343
|
/* @__PURE__ */ jsx27(DropdownMenuTrigger3, { asChild: true, children: /* @__PURE__ */ jsx27(Button22, { variant: "quiet", icon: /* @__PURE__ */ jsx27(PlusGlyph, {}), children: "Add" }) }),
|
|
6295
6344
|
/* @__PURE__ */ jsxs25(DropdownMenuContent3, { align: "end", children: [
|
|
6296
6345
|
/* @__PURE__ */ jsx27(DropdownMenuItem3, { onSelect: () => patch({ secrets: [...draft.secrets, { key: "", label: "", value: "" }] }), children: "Secret field" }),
|
|
6346
|
+
!hasSecureNote ? /* @__PURE__ */ jsx27(DropdownMenuItem3, { onSelect: () => patch({ secrets: [...draft.secrets, secureNoteDraft()] }), children: "Secure note" }) : null,
|
|
6297
6347
|
/* @__PURE__ */ jsx27(DropdownMenuItem3, { onSelect: () => patch({ custom: [...draft.custom, { key: `custom_${draft.custom.length + 1}_${Date.now() % 1e5}`, label: "", value: "" }] }), children: "Text field" }),
|
|
6298
6348
|
!tagsVisible ? /* @__PURE__ */ jsx27(DropdownMenuItem3, { onSelect: () => setShowTags(true), children: "Tags" }) : null,
|
|
6299
6349
|
!descriptionVisible ? /* @__PURE__ */ jsx27(DropdownMenuItem3, { onSelect: () => setShowDescription(true), children: "Description" }) : null,
|
|
@@ -6326,7 +6376,7 @@ function ItemPane(props) {
|
|
|
6326
6376
|
}
|
|
6327
6377
|
),
|
|
6328
6378
|
filesProps ? /* @__PURE__ */ jsx27(FilesSection, { ...filesProps, editing: true }) : mode === "new" && owner !== "person" ? /* @__PURE__ */ jsx27(DraftFilesSection, { files: queuedFiles, onFiles: setQueuedFiles }) : null
|
|
6329
|
-
] }) : item ? /* @__PURE__ */ jsxs25(
|
|
6379
|
+
] }) : item ? /* @__PURE__ */ jsxs25(Fragment18, { children: [
|
|
6330
6380
|
/* @__PURE__ */ jsxs25(VaultSection, { children: [
|
|
6331
6381
|
declared.map((f) => {
|
|
6332
6382
|
if (f.storage === "metadata") {
|
|
@@ -6647,7 +6697,7 @@ function refusalText(reason) {
|
|
|
6647
6697
|
// src/lists/RestorePanel.tsx
|
|
6648
6698
|
import { useEffect as useEffect18, useState as useState29 } from "react";
|
|
6649
6699
|
import { Button as Button24 } from "@ai-matrx/design-system/controls";
|
|
6650
|
-
import { Fragment as
|
|
6700
|
+
import { Fragment as Fragment19, jsx as jsx29, jsxs as jsxs27 } from "react/jsx-runtime";
|
|
6651
6701
|
var count = (n, one) => `${n} ${one}${n === 1 ? "" : "s"}`;
|
|
6652
6702
|
function RestorePanel({ lists, item, restore, onClose }) {
|
|
6653
6703
|
const [preview, setPreview] = useState29(null);
|
|
@@ -6692,7 +6742,7 @@ function RestorePanel({ lists, item, restore, onClose }) {
|
|
|
6692
6742
|
title: `Restore "${item.name}"`,
|
|
6693
6743
|
size: "md",
|
|
6694
6744
|
onClose,
|
|
6695
|
-
footer: /* @__PURE__ */ jsxs27(
|
|
6745
|
+
footer: /* @__PURE__ */ jsxs27(Fragment19, { children: [
|
|
6696
6746
|
/* @__PURE__ */ jsx29(Button24, { variant: "quiet", onClick: onClose, children: refused ? "Close" : "Cancel" }),
|
|
6697
6747
|
refused ? null : /* @__PURE__ */ jsx29(Button24, { variant: "primary", icon: /* @__PURE__ */ jsx29(RestoreGlyph, {}), disabled: busy || loading || lists.preview !== void 0 && preview === null, onClick: () => void run(), children: busy ? "Restoring\u2026" : "Restore" })
|
|
6698
6748
|
] }),
|
|
@@ -7190,7 +7240,7 @@ function addPasskeyFailure(message2) {
|
|
|
7190
7240
|
var isRevoked = (d) => d.revokedAt !== null;
|
|
7191
7241
|
|
|
7192
7242
|
// src/devices/DevicesPanel.tsx
|
|
7193
|
-
import { Fragment as
|
|
7243
|
+
import { Fragment as Fragment20, jsx as jsx33, jsxs as jsxs31 } from "react/jsx-runtime";
|
|
7194
7244
|
var messageOf3 = (e, fallback) => e instanceof Error && e.message ? e.message : fallback;
|
|
7195
7245
|
function ErrorLine2({ text }) {
|
|
7196
7246
|
return text ? /* @__PURE__ */ jsx33("p", { role: "alert", className: "px-1 text-sm text-destructive", children: text }) : null;
|
|
@@ -7321,7 +7371,7 @@ function ApprovePanel({ port, host, onClose, approvalKey, label, kind = "browser
|
|
|
7321
7371
|
};
|
|
7322
7372
|
const canApprove = Boolean(key && passkeys && here && methods?.passkey && !approvedUntil);
|
|
7323
7373
|
const title = isMac ? "Approve this Mac" : name ? `Approve ${name}` : "Approve this browser";
|
|
7324
|
-
const footer = approvedUntil ? /* @__PURE__ */ jsx33(Button28, { variant: "primary", onClick: onClose, children: "Done" }) : /* @__PURE__ */ jsxs31(
|
|
7374
|
+
const footer = approvedUntil ? /* @__PURE__ */ jsx33(Button28, { variant: "primary", onClick: onClose, children: "Done" }) : /* @__PURE__ */ jsxs31(Fragment20, { children: [
|
|
7325
7375
|
/* @__PURE__ */ jsx33(Button28, { variant: "quiet", disabled: busy !== null, onClick: refuse, children: key ? "Refuse" : "Close" }),
|
|
7326
7376
|
canApprove ? /* @__PURE__ */ jsx33(Button28, { variant: "primary", icon: /* @__PURE__ */ jsx33(FingerprintGlyph, {}), disabled: busy !== null, onClick: () => void approve(), children: busy === "approve" ? "Approving\u2026" : "Approve with passkey" }) : null
|
|
7327
7377
|
] });
|
|
@@ -7329,7 +7379,7 @@ function ApprovePanel({ port, host, onClose, approvalKey, label, kind = "browser
|
|
|
7329
7379
|
"This link names no key. Start again from ",
|
|
7330
7380
|
where,
|
|
7331
7381
|
"."
|
|
7332
|
-
] }) }) : /* @__PURE__ */ jsxs31(
|
|
7382
|
+
] }) }) : /* @__PURE__ */ jsxs31(Fragment20, { children: [
|
|
7333
7383
|
/* @__PURE__ */ jsxs31(VaultSection, { title: "What is asking", children: [
|
|
7334
7384
|
/* @__PURE__ */ jsx33(VaultRow, { label: "Asking", hint: "Approve only if you just asked", children: asker }),
|
|
7335
7385
|
name ? /* @__PURE__ */ jsx33(VaultRow, { label: "Name", children: /* @__PURE__ */ jsx33("span", { className: "block truncate", children: name }) }) : null,
|
|
@@ -7629,7 +7679,7 @@ function useNativeImport(bridge, stillAllowed, onImported) {
|
|
|
7629
7679
|
}
|
|
7630
7680
|
|
|
7631
7681
|
// src/native/NativeImportPanel.tsx
|
|
7632
|
-
import { Fragment as
|
|
7682
|
+
import { Fragment as Fragment21, jsx as jsx34, jsxs as jsxs32 } from "react/jsx-runtime";
|
|
7633
7683
|
var TONE = {
|
|
7634
7684
|
eligible: "success",
|
|
7635
7685
|
committed: "success",
|
|
@@ -7673,16 +7723,16 @@ function Importer({ bridge, readLimits, activeOrganizationId, organizations, onC
|
|
|
7673
7723
|
const yes = await confirm13({ title: `Add ${plural2(ready, "passkey")} to ${orgName}?`, description: "Passkeys already there are skipped.", confirmLabel: "Import" });
|
|
7674
7724
|
if (yes) await flow.confirm();
|
|
7675
7725
|
};
|
|
7676
|
-
const footer = preview ? /* @__PURE__ */ jsxs32(
|
|
7726
|
+
const footer = preview ? /* @__PURE__ */ jsxs32(Fragment21, { children: [
|
|
7677
7727
|
/* @__PURE__ */ jsx34(Button29, { variant: "quiet", disabled: busy, onClick: () => void flow.cancel(), children: "Cancel" }),
|
|
7678
7728
|
/* @__PURE__ */ jsxs32(Button29, { variant: "primary", icon: /* @__PURE__ */ jsx34(ImportGlyph, { className: "size-4" }), disabled: busy || ready === 0, onClick: () => void importNow(), children: [
|
|
7679
7729
|
"Import ",
|
|
7680
7730
|
ready
|
|
7681
7731
|
] })
|
|
7682
|
-
] }) : status ? active ? /* @__PURE__ */ jsxs32(
|
|
7732
|
+
] }) : status ? active ? /* @__PURE__ */ jsxs32(Fragment21, { children: [
|
|
7683
7733
|
/* @__PURE__ */ jsx34(Button29, { variant: "outline", disabled: busy, onClick: () => void flow.refresh(), children: "Refresh" }),
|
|
7684
7734
|
/* @__PURE__ */ jsx34(Button29, { variant: "outline", disabled: busy, onClick: () => void flow.cancel(), children: "Cancel import" })
|
|
7685
|
-
] }) : /* @__PURE__ */ jsxs32(
|
|
7735
|
+
] }) : /* @__PURE__ */ jsxs32(Fragment21, { children: [
|
|
7686
7736
|
/* @__PURE__ */ jsx34(Button29, { variant: "quiet", onClick: flow.reset, children: "New file" }),
|
|
7687
7737
|
/* @__PURE__ */ jsx34(Button29, { variant: "primary", onClick: onClose, children: "Done" })
|
|
7688
7738
|
] }) : /* @__PURE__ */ jsx34(Button29, { variant: "quiet", onClick: onClose, children: "Close" });
|
|
@@ -7721,7 +7771,7 @@ import { GlobeIcon as GlobeIcon4 } from "@ai-matrx/design-system/icons";
|
|
|
7721
7771
|
// src/extension/CaptureCard.tsx
|
|
7722
7772
|
import { useState as useState36, useSyncExternalStore as useSyncExternalStore3 } from "react";
|
|
7723
7773
|
import { Button as Button30, SearchField as SearchField3 } from "@ai-matrx/design-system/controls";
|
|
7724
|
-
import { Fragment as
|
|
7774
|
+
import { Fragment as Fragment22, jsx as jsx35, jsxs as jsxs33 } from "react/jsx-runtime";
|
|
7725
7775
|
var SEARCH_FROM = 4;
|
|
7726
7776
|
function CaptureCard({ capture, onChanged }) {
|
|
7727
7777
|
const prompt = useSyncExternalStore3(capture.subscribe, capture.get, capture.get);
|
|
@@ -7754,7 +7804,7 @@ function CaptureCard({ capture, onChanged }) {
|
|
|
7754
7804
|
] }),
|
|
7755
7805
|
/* @__PURE__ */ jsx35(Button30, { variant: "quiet", icon: /* @__PURE__ */ jsx35(XGlyph, {}), "aria-label": "Not now", disabled: busy, onClick: () => void decide({ action: "dismiss" }) })
|
|
7756
7806
|
] }),
|
|
7757
|
-
prompt.unavailable ? /* @__PURE__ */ jsx35("p", { className: "text-xs text-muted-foreground", children: "Save it by hand with Save a login." }) : /* @__PURE__ */ jsxs33(
|
|
7807
|
+
prompt.unavailable ? /* @__PURE__ */ jsx35("p", { className: "text-xs text-muted-foreground", children: "Save it by hand with Save a login." }) : /* @__PURE__ */ jsxs33(Fragment22, { children: [
|
|
7758
7808
|
existing.length > 0 ? /* @__PURE__ */ jsxs33("div", { className: "flex flex-col gap-1", children: [
|
|
7759
7809
|
existing.length >= SEARCH_FROM ? /* @__PURE__ */ jsx35(SearchField3, { value: q, onChange: (e) => setQ(e.target.value), placeholder: "Search logins", "aria-label": "Search logins to update" }) : null,
|
|
7760
7810
|
/* @__PURE__ */ jsxs33("ul", { className: "flex max-h-36 flex-col gap-px overflow-y-auto", children: [
|
|
@@ -7860,7 +7910,7 @@ import { useState as useState38 } from "react";
|
|
|
7860
7910
|
import { Popover as Popover2, PopoverContent as PopoverContent2, PopoverTrigger as PopoverTrigger2 } from "@ai-matrx/design-system";
|
|
7861
7911
|
import { Button as Button32 } from "@ai-matrx/design-system/controls";
|
|
7862
7912
|
import { CopyIcon as CopyIcon8 } from "@ai-matrx/design-system/icons";
|
|
7863
|
-
import { Fragment as
|
|
7913
|
+
import { Fragment as Fragment23, jsx as jsx37, jsxs as jsxs35 } from "react/jsx-runtime";
|
|
7864
7914
|
var HOLD_MS = 6e4;
|
|
7865
7915
|
function PageGenerator({ fields }) {
|
|
7866
7916
|
const limits = useGeneratorLimitsSource();
|
|
@@ -7911,12 +7961,12 @@ function PageGenerator({ fields }) {
|
|
|
7911
7961
|
}
|
|
7912
7962
|
};
|
|
7913
7963
|
const value = held.value;
|
|
7914
|
-
return /* @__PURE__ */ jsxs35(
|
|
7964
|
+
return /* @__PURE__ */ jsxs35(Fragment23, { children: [
|
|
7915
7965
|
/* @__PURE__ */ jsx37(
|
|
7916
7966
|
VaultRow,
|
|
7917
7967
|
{
|
|
7918
7968
|
label: "New password",
|
|
7919
|
-
actions: /* @__PURE__ */ jsxs35(
|
|
7969
|
+
actions: /* @__PURE__ */ jsxs35(Fragment23, { children: [
|
|
7920
7970
|
value ? /* @__PURE__ */ jsx37(Button32, { variant: "quiet", icon: /* @__PURE__ */ jsx37(CopyIcon8, {}), "aria-label": "Copy password", onClick: () => void copy(value, "Password") }) : null,
|
|
7921
7971
|
/* @__PURE__ */ jsxs35(Popover2, { open, onOpenChange: setOpen, children: [
|
|
7922
7972
|
/* @__PURE__ */ jsx37(PopoverTrigger2, { asChild: true, children: /* @__PURE__ */ jsx37(Button32, { variant: "outline", icon: /* @__PURE__ */ jsx37(KeyGlyph, {}), disabled: busy, children: "Generate" }) }),
|
|
@@ -9062,6 +9112,28 @@ function trashItem(r, ctx) {
|
|
|
9062
9112
|
createdAt: ""
|
|
9063
9113
|
};
|
|
9064
9114
|
}
|
|
9115
|
+
async function withTypes(items, door, ctx) {
|
|
9116
|
+
if (!door.schema || items.length === 0) return items;
|
|
9117
|
+
const keys = /* @__PURE__ */ new Map();
|
|
9118
|
+
const CHUNK = 100;
|
|
9119
|
+
try {
|
|
9120
|
+
for (let i = 0; i < items.length; i += CHUNK) {
|
|
9121
|
+
const ids = items.slice(i, i + CHUNK).map((x) => x.id);
|
|
9122
|
+
const { data, error } = await door.schema("users").from("credential_items").select("id,definition_key").in("id", ids);
|
|
9123
|
+
if (error) throw new Error(error.message || "credential_items read failed");
|
|
9124
|
+
for (const r of Array.isArray(data) ? data : []) {
|
|
9125
|
+
if (typeof r.id === "string" && typeof r.definition_key === "string" && r.definition_key) keys.set(r.id, r.definition_key);
|
|
9126
|
+
}
|
|
9127
|
+
}
|
|
9128
|
+
} catch (e) {
|
|
9129
|
+
console.warn("[vault] Trash item types could not be read; rows say Credential", e);
|
|
9130
|
+
return items;
|
|
9131
|
+
}
|
|
9132
|
+
return items.map((it) => {
|
|
9133
|
+
const key = keys.get(it.id);
|
|
9134
|
+
return key ? { ...it, definitionKey: key, definitionLabel: ctx.definition(key)?.label ?? humanize(key) } : it;
|
|
9135
|
+
});
|
|
9136
|
+
}
|
|
9065
9137
|
var previewOf = async (door, id) => parseRecoveryPreview(await call(door, "vault_recovery_preview", { p_id: id }));
|
|
9066
9138
|
function createListsPort(ctx, door) {
|
|
9067
9139
|
return {
|
|
@@ -9094,7 +9166,8 @@ function createListsPort(ctx, door) {
|
|
|
9094
9166
|
if (rows.length < PAGE2) break;
|
|
9095
9167
|
}
|
|
9096
9168
|
const items = all.map((r) => trashItem(r, ctx)).filter((i) => i !== null);
|
|
9097
|
-
|
|
9169
|
+
const unique = [...new Map(items.map((i) => [i.id, i])).values()];
|
|
9170
|
+
return withTypes(unique, door, ctx);
|
|
9098
9171
|
}
|
|
9099
9172
|
},
|
|
9100
9173
|
favorites: {
|
|
@@ -9117,16 +9190,25 @@ function createListsPort(ctx, door) {
|
|
|
9117
9190
|
import * as account6 from "@ai-matrx/api/account";
|
|
9118
9191
|
|
|
9119
9192
|
// src/secret-field-in.ts
|
|
9120
|
-
function
|
|
9193
|
+
function settingsIn(s) {
|
|
9121
9194
|
const envKey = s.envKey?.trim() || null;
|
|
9122
9195
|
return {
|
|
9123
|
-
field_key: fieldKeyOf(s.label),
|
|
9124
|
-
value: s.value,
|
|
9125
|
-
handling: s.handling ?? "revealable",
|
|
9126
9196
|
...envKey ? { env_key: envKey } : {},
|
|
9127
9197
|
...envKey && s.injectIntoSandbox ? { inject_into_sandbox: true } : {}
|
|
9128
9198
|
};
|
|
9129
9199
|
}
|
|
9200
|
+
function secretFieldIn(s) {
|
|
9201
|
+
return {
|
|
9202
|
+
field_key: s.key.trim() || fieldKeyOf(s.label),
|
|
9203
|
+
value: s.value,
|
|
9204
|
+
handling: s.handling ?? "revealable",
|
|
9205
|
+
...s.description ? { description: s.description } : {},
|
|
9206
|
+
...settingsIn(s)
|
|
9207
|
+
};
|
|
9208
|
+
}
|
|
9209
|
+
function declaredFieldIn(f, value, settings) {
|
|
9210
|
+
return { field_key: f.key, value, handling: settings?.handling ?? f.handling, ...settingsIn(settings ?? {}) };
|
|
9211
|
+
}
|
|
9130
9212
|
|
|
9131
9213
|
// src/sharing/api.ts
|
|
9132
9214
|
function grantOf(w) {
|
|
@@ -9227,7 +9309,7 @@ function createSharingPort(ctx, options = {}) {
|
|
|
9227
9309
|
initiation: "user",
|
|
9228
9310
|
non_secret_fields: [...meta.map((f) => ({ key: f.key, label: f.label, value: draft.values[f.key] ?? "" })), ...draft.custom.filter((c) => c.label.trim() !== "").map((c) => ({ key: c.key || fieldKeyOf(c.label), label: c.label, value: c.value }))],
|
|
9229
9311
|
fields: [
|
|
9230
|
-
...encrypted.map((f) => (
|
|
9312
|
+
...encrypted.map((f) => declaredFieldIn(f, draft.values[f.key] ?? "", draft.fieldSettings?.[f.key])),
|
|
9231
9313
|
...draft.secrets.filter((s) => s.label.trim() !== "" && s.value !== "").map(secretFieldIn)
|
|
9232
9314
|
]
|
|
9233
9315
|
}
|
|
@@ -9356,7 +9438,7 @@ async function readNativeImportLimits(api, organizationId) {
|
|
|
9356
9438
|
var recoveryOf = (w) => w.lifecycle?.vault_recovery;
|
|
9357
9439
|
var isDeleted = (w) => recoveryOf(w)?.state === "deleted";
|
|
9358
9440
|
var MATCH_MODES2 = ["host", "domain", "exact", "never"];
|
|
9359
|
-
var FIELD_WORDS = { totp_seed: "One-time password key", authenticator_last_time_step: "Last code used" };
|
|
9441
|
+
var FIELD_WORDS = { secure_notes: "Secure note", totp_seed: "One-time password key", authenticator_last_time_step: "Last code used" };
|
|
9360
9442
|
var handlingOf = (v) => v === "visible" || v === "sealed" ? v : "revealable";
|
|
9361
9443
|
function fieldOf(w, def) {
|
|
9362
9444
|
const declared = def?.fields.find((f) => f.key === w.field_key);
|
|
@@ -9365,7 +9447,8 @@ function fieldOf(w, def) {
|
|
|
9365
9447
|
id: w.id,
|
|
9366
9448
|
key: w.field_key,
|
|
9367
9449
|
label: declared?.label ?? FIELD_WORDS[w.field_key] ?? humanize(w.field_key),
|
|
9368
|
-
|
|
9450
|
+
// A field no type declares still edits as several lines when its key says so (an old "Secure note").
|
|
9451
|
+
kind: declared?.kind ?? (isMultilineKey(w.field_key) ? "multiline" : handling === "visible" ? "text" : "secret"),
|
|
9369
9452
|
handling,
|
|
9370
9453
|
editable: w.editable ?? true,
|
|
9371
9454
|
envKey: w.env_key ?? null,
|
|
@@ -9520,7 +9603,7 @@ function createApiVaultPort(api, options = {}) {
|
|
|
9520
9603
|
initiation: "user",
|
|
9521
9604
|
non_secret_fields: [...meta.map((f) => ({ key: f.key, label: f.label, value: draft.values[f.key] ?? "" })), ...draft.custom.filter((c) => c.label.trim() !== "").map((c) => ({ key: c.key || fieldKeyOf(c.label), label: c.label, value: c.value }))],
|
|
9522
9605
|
fields: [
|
|
9523
|
-
...encrypted.map((f) => (
|
|
9606
|
+
...encrypted.map((f) => declaredFieldIn(f, draft.values[f.key] ?? "", draft.fieldSettings?.[f.key])),
|
|
9524
9607
|
...draft.secrets.filter((s) => s.label.trim() !== "" && s.value !== "").map(secretFieldIn),
|
|
9525
9608
|
// Backup codes on a type that does not declare them (a website login): their own encrypted field.
|
|
9526
9609
|
...!declared.some((f) => f.key === RECOVERY_CODES_KEY) && (draft.values[RECOVERY_CODES_KEY] ?? "").trim() !== "" ? [{ field_key: RECOVERY_CODES_KEY, value: parseRecoveryCodes(draft.values[RECOVERY_CODES_KEY] ?? "").join("\n"), handling: "revealable", description: "One-time account recovery codes" }] : []
|