@ai-matrx/vault 0.1.12 → 0.1.14

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/dist/index.d.cts CHANGED
@@ -86,6 +86,8 @@ interface VaultItem {
86
86
  accessMode: string | null;
87
87
  /** The person who owns the item (`user_id`). For the person's own items this is them. */
88
88
  ownerUserId: string | null;
89
+ /** The whole item is turned off (an item restored from Trash comes back off): nothing can use it until it is turned on. */
90
+ turnedOff?: boolean;
89
91
  /** Set when the item is in the trash: what restoring it needs. */
90
92
  deletion: {
91
93
  deletionId: string | null;
@@ -742,6 +744,8 @@ interface ItemSettingsPatch {
742
744
  browserFillEnabled?: boolean;
743
745
  /** The complete list of websites (used to add a promoted address). */
744
746
  loginUrls?: string[];
747
+ /** Turn the whole item on (true) or off (false). */
748
+ active?: boolean;
745
749
  }
746
750
  interface NewFieldInput {
747
751
  key: string;
@@ -1274,7 +1278,7 @@ interface SharingPortOptions {
1274
1278
  /**
1275
1279
  * THE vault client for every host: a VaultPort over the generated `@ai-matrx/api`. The web app, the
1276
1280
  * extension and the desktop app hand it their own `Api` (their own sign-in and organization) and get
1277
- * identical behaviour; none of them keeps a hand-written vault client.
1281
+ * identical behavior; none of them keeps a hand-written vault client.
1278
1282
  */
1279
1283
 
1280
1284
  interface ApiVaultPortOptions {
@@ -1300,7 +1304,7 @@ declare function IdentityGate({ identity, children }: {
1300
1304
  identity: VaultIdentity | undefined;
1301
1305
  children: ReactNode;
1302
1306
  }): react.JSX.Element;
1303
- /** True for the rejection a cancelled confirmation produces (callers stay quiet about it). */
1307
+ /** True for the rejection a canceled confirmation produces (callers stay quiet about it). */
1304
1308
  declare const wasCancelled: (e: unknown) => boolean;
1305
1309
 
1306
1310
  /** Reads the organization's ceilings. Raw knob values are fine: they are validated here. */
package/dist/index.d.ts CHANGED
@@ -86,6 +86,8 @@ interface VaultItem {
86
86
  accessMode: string | null;
87
87
  /** The person who owns the item (`user_id`). For the person's own items this is them. */
88
88
  ownerUserId: string | null;
89
+ /** The whole item is turned off (an item restored from Trash comes back off): nothing can use it until it is turned on. */
90
+ turnedOff?: boolean;
89
91
  /** Set when the item is in the trash: what restoring it needs. */
90
92
  deletion: {
91
93
  deletionId: string | null;
@@ -742,6 +744,8 @@ interface ItemSettingsPatch {
742
744
  browserFillEnabled?: boolean;
743
745
  /** The complete list of websites (used to add a promoted address). */
744
746
  loginUrls?: string[];
747
+ /** Turn the whole item on (true) or off (false). */
748
+ active?: boolean;
745
749
  }
746
750
  interface NewFieldInput {
747
751
  key: string;
@@ -1274,7 +1278,7 @@ interface SharingPortOptions {
1274
1278
  /**
1275
1279
  * THE vault client for every host: a VaultPort over the generated `@ai-matrx/api`. The web app, the
1276
1280
  * extension and the desktop app hand it their own `Api` (their own sign-in and organization) and get
1277
- * identical behaviour; none of them keeps a hand-written vault client.
1281
+ * identical behavior; none of them keeps a hand-written vault client.
1278
1282
  */
1279
1283
 
1280
1284
  interface ApiVaultPortOptions {
@@ -1300,7 +1304,7 @@ declare function IdentityGate({ identity, children }: {
1300
1304
  identity: VaultIdentity | undefined;
1301
1305
  children: ReactNode;
1302
1306
  }): react.JSX.Element;
1303
- /** True for the rejection a cancelled confirmation produces (callers stay quiet about it). */
1307
+ /** True for the rejection a canceled confirmation produces (callers stay quiet about it). */
1304
1308
  declare const wasCancelled: (e: unknown) => boolean;
1305
1309
 
1306
1310
  /** Reads the organization's ceilings. Raw knob values are fine: they are validated here. */
package/dist/index.js CHANGED
@@ -684,7 +684,7 @@ function SecretRow({ port, item, field, extra, onTurnOn }) {
684
684
  const [error, setError] = useState5(null);
685
685
  const sealed = field.handling === "sealed";
686
686
  const visible = field.handling === "visible";
687
- const off = field.active === false;
687
+ const off = field.active === false || item.turnedOff === true;
688
688
  const canSee = !sealed && !off && (visible ? item.capabilities.canUse : item.capabilities.canReveal);
689
689
  useEffect5(() => {
690
690
  if (!visible || !canSee) return;
@@ -4088,7 +4088,7 @@ import { BlobReader as BlobReader2, ZipReader as ZipReader2 } from "@zip.js/zip.
4088
4088
  var safe = (value) => Number.isSafeInteger(value) && value >= 0;
4089
4089
  var unsafeName = (name) => /[\\\0-\x1F\x7F-\x9F]/.test(name);
4090
4090
  function stopIfCancelled(signal) {
4091
- if (signal?.aborted) throw new Error("The archive import was cancelled.");
4091
+ if (signal?.aborted) throw new Error("The archive import was canceled.");
4092
4092
  }
4093
4093
  function hasWarnings(reader, entry) {
4094
4094
  return Boolean(reader.warnings?.length || entry.warnings?.length);
@@ -4189,7 +4189,7 @@ async function openBoundedZip(file, limits, signal) {
4189
4189
  };
4190
4190
  } catch (error) {
4191
4191
  await reader.close();
4192
- if (signal?.aborted) throw new Error("The archive import was cancelled.");
4192
+ if (signal?.aborted) throw new Error("The archive import was canceled.");
4193
4193
  throw error;
4194
4194
  }
4195
4195
  }
@@ -4228,7 +4228,7 @@ async function readDashlaneCsvArchive(file, limits, signal) {
4228
4228
  return { credentialsText, omittedCsvCount };
4229
4229
  } catch (error) {
4230
4230
  credentialsText = void 0;
4231
- if (signal?.aborted) throw new Error("The Dashlane import was cancelled.");
4231
+ if (signal?.aborted) throw new Error("The Dashlane import was canceled.");
4232
4232
  throw error;
4233
4233
  } finally {
4234
4234
  credentialsText = void 0;
@@ -4363,7 +4363,7 @@ function hasValidStructuredImportFileNotices(value, maxCount) {
4363
4363
  }
4364
4364
 
4365
4365
  // src/io/parse-source.ts
4366
- var cancelled = () => new Error("The import was cancelled.");
4366
+ var cancelled = () => new Error("The import was canceled.");
4367
4367
  function parseStructured(source, file, limits, signal) {
4368
4368
  const descriptor = structuredImportSource(source);
4369
4369
  if (!descriptor) return Promise.reject(new Error("This kind of file cannot be imported."));
@@ -5770,13 +5770,19 @@ function ItemPane(props) {
5770
5770
  }
5771
5771
  }
5772
5772
  const offFields = item ? item.fields.filter((f) => !f.active) : [];
5773
+ const itemOff = item?.turnedOff === true;
5773
5774
  const seedField = item?.fields.find((f) => f.key === OTP_SEED_KEY) ?? null;
5774
5775
  const canTurnOn = Boolean(item && canEdit);
5775
5776
  async function turnOn(fields) {
5776
- if (!item || fields.length === 0) return;
5777
+ if (!item) return;
5777
5778
  setError(null);
5778
5779
  try {
5780
+ if (item.turnedOff) await confirmed(() => port.fields.updateItem(item, { active: true }));
5779
5781
  for (const f of fields) await confirmed(() => port.fields.updateField(item, f.id, { active: true }));
5782
+ if (fields.some((f) => f.key === OTP_SEED_KEY)) {
5783
+ const codes = await port.authenticator.get(item);
5784
+ if (codes && !codes.enabled) await confirmed(() => port.authenticator.setEnabled(item, true));
5785
+ }
5780
5786
  onChanged();
5781
5787
  } catch (e) {
5782
5788
  if (!wasCancelled(e)) setError(e instanceof Error ? e.message : "It could not be turned on.");
@@ -5879,8 +5885,8 @@ function ItemPane(props) {
5879
5885
  header,
5880
5886
  error ? /* @__PURE__ */ jsx26("div", { role: "alert", className: "border-b border-border bg-muted px-5 py-2 text-sm text-destructive", children: error }) : null,
5881
5887
  notice && !editing ? /* @__PURE__ */ jsx26("div", { role: "status", className: "border-b border-border bg-muted px-5 py-2 text-sm text-warning", children: notice }) : null,
5882
- item && !editing && offFields.length > 0 ? /* @__PURE__ */ jsxs24("div", { role: "status", className: "flex items-center gap-3 border-b border-border bg-muted px-5 py-2 text-sm", children: [
5883
- /* @__PURE__ */ jsx26("span", { className: "min-w-0 flex-1 truncate text-warning", children: offFields.length === 1 ? "1 field is turned off" : `${offFields.length} fields are turned off` }),
5888
+ item && !editing && (itemOff || offFields.length > 0) ? /* @__PURE__ */ jsxs24("div", { role: "status", className: "flex items-center gap-3 border-b border-border bg-muted px-5 py-2 text-sm", children: [
5889
+ /* @__PURE__ */ jsx26("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` }),
5884
5890
  canTurnOn ? /* @__PURE__ */ jsx26(TurnOnButton, { label: "all fields", onTurnOn: () => turnOn(offFields) }) : null
5885
5891
  ] }) : null,
5886
5892
  /* @__PURE__ */ jsx26("div", { className: "min-h-0 flex-1 overflow-y-auto", children: /* @__PURE__ */ jsx26("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__ */ jsxs24(Fragment16, { children: [
@@ -6983,7 +6989,7 @@ var plural2 = (n, one) => `${n} ${one}${n === 1 ? "" : "s"}`;
6983
6989
  function terminalMessage(s) {
6984
6990
  if (s.phase === "completed") return `Imported ${plural2(s.committed, "passkey")}.`;
6985
6991
  if (s.phase === "partial") return `${s.committed} imported; ${s.unsupported + s.failed + s.uncertain + s.not_attempted} need attention.`;
6986
- if (s.phase === "cancelled") return "Import cancelled. Nothing else will be imported.";
6992
+ if (s.phase === "cancelled") return "Import canceled. Nothing else will be imported.";
6987
6993
  if (s.phase === "unavailable") return "Passkey import is unavailable here.";
6988
6994
  if (s.phase === "failed") return "The import did not finish. Recover it before using a new file.";
6989
6995
  return s.message;
@@ -7168,7 +7174,7 @@ function useNativeImport(bridge, stillAllowed, onImported) {
7168
7174
  present(g, { kind: "status", status: result, message: terminalMessage(result) });
7169
7175
  if (!done && ACTIVE_PHASES.has(result.phase)) schedulePoll(active.id);
7170
7176
  } catch (e) {
7171
- keepOperation(g, fail(e, "The import could not be cancelled."));
7177
+ keepOperation(g, fail(e, "The import could not be canceled."));
7172
7178
  } finally {
7173
7179
  if (current(g)) setBusy(false);
7174
7180
  }
@@ -8460,6 +8466,7 @@ function createFieldsPort(ctx) {
8460
8466
  if (patch.uriMatchMode !== void 0) body.uri_match_mode = patch.uriMatchMode;
8461
8467
  if (patch.browserFillEnabled !== void 0) body.browser_fill_enabled = patch.browserFillEnabled;
8462
8468
  if (patch.loginUrls !== void 0) body.login_urls = patch.loginUrls;
8469
+ if (patch.active !== void 0) body.status = patch.active ? "active" : "disabled";
8463
8470
  await account3.updateItem(api, { path: { item_id: item.id }, body }, ctx.optsFor(item));
8464
8471
  return reread(item);
8465
8472
  },
@@ -8872,6 +8879,7 @@ function itemOf(w, owner, defs, auth) {
8872
8879
  uriMatchMode: MATCH_MODES2.find((m) => m === w.uri_match_mode) ?? "host",
8873
8880
  browserFillEnabled: w.browser_fill_enabled ?? true,
8874
8881
  accessMode: w.access_mode ?? null,
8882
+ turnedOff: w.status === "disabled",
8875
8883
  ownerUserId: w.user_id ?? null,
8876
8884
  deletion: recovery?.state === "deleted" ? { deletionId: typeof recovery.deletion_id === "string" ? recovery.deletion_id : null, deletedAt: typeof recovery.deleted_at === "string" ? recovery.deleted_at : null } : null,
8877
8885
  updatedAt: w.updated_at,
@@ -8931,9 +8939,12 @@ function createApiVaultPort(api, options = {}) {
8931
8939
  const authP = retrying(() => apps2.listAuthenticators(api));
8932
8940
  const userP = retrying(() => account9.listItems(api, { query: { principal_type: "user" } }));
8933
8941
  const sharedP = retrying(() => account9.sharedWithMe(api));
8942
+ const quiet = (p) => void p.catch(() => void 0);
8943
+ [catalogP, authP, userP, sharedP].forEach(quiet);
8934
8944
  const org = options.organizations ? null : await retrying(() => platform.listMyOrganizations(api));
8935
8945
  orgs = [...new Map((options.organizations ?? (org?.organizations ?? []).filter((o) => !o.archived_at).map((o) => ({ id: o.id, name: o.name }))).map((o) => [o.id, o])).values()];
8936
8946
  const orgListsP = orgs.map((o) => retrying(() => account9.listItems(api, { query: { principal_type: "organization", organization_id: o.id } }, { organizationId: o.id })));
8947
+ orgListsP.forEach(quiet);
8937
8948
  const [catalog, mine] = await Promise.all([catalogP, userP]);
8938
8949
  const [authSettled, sharedSettled, ...orgSettled] = await Promise.allSettled([authP, sharedP, ...orgListsP]);
8939
8950
  const unavailable = [];