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