@ai-matrx/vault 0.1.26 → 0.1.27

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
@@ -1471,4 +1471,48 @@ interface RowMenuEntry {
1471
1471
  /** The entries of the row a right-click landed on (`[data-item]`), else none. */
1472
1472
  declare function rowMenuEntriesAt(target: Element | null | undefined): readonly RowMenuEntry[];
1473
1473
 
1474
- export { type ApiVaultPortOptions, CATEGORIES, CONFIRM_RETURN_KEY, type CategoryId, type Confirmed, type CopyOptions, DEFAULT_LOCATION, type DefinitionField, type FieldHandling, type FieldKind, GenerateButton, HIDDEN_ITEM_TAG, type IdentityAccount, IdentityGate, type IdentityMethod, type ItemDraft, LOCKED_MESSAGE, type NoticeKind, type Notify, type ReturnStore, type RowMenuEntry, type RowMenuEntryKind, type SaveResult, type SupabaseAuthLike, type SupabaseIdentityOptions, type TotpReading, type UriMatchMode, type UrlGuess, type VaultAgentScope, VaultApp, type VaultAppProps, type VaultAttachment, type VaultAuthenticator, type VaultClipboard, type VaultCustomField, type VaultDefinition, type VaultField, type VaultHostCapabilities, type VaultIdentity, type VaultInventory, type VaultItem, type VaultItemCapabilities, type VaultKnobs, type VaultLayout, type VaultLocation, type VaultLock, VaultLockedError, type VaultOrganizationRef, type VaultOwner, type VaultPort, type VaultSelection, type VaultSnapshot, type VaultSort, type VaultUserStateDoor, categoryOf, copyValue, createApiVaultPort, createSupabaseIdentity, createVaultKnobs, guardPort, inferFromUrl, isHiddenItem, itemIdAt, locationFromParams, locationToParams, loginSiteOf, matchesQuery, needsRecentSignIn, parseDefinitions, providerOf, rowMenuEntriesAt, siteDomainOf, sortItems, useConfirmed, vaultInventoryScope, vaultItemFacts, wasCancelled };
1474
+ /**
1475
+ * AN EMPTY CREDENTIAL IS A FACT; AN EMPTY READ OF A FULL ONE IS A FAILURE (DD-160, lane
1476
+ * ERRORS-HONEST 2026-09-24).
1477
+ *
1478
+ * RLS refuses a row by returning nothing, so a list that reads a credential's fields and gets `[]`
1479
+ * cannot tell "there is nothing in it" from "the database filtered the read" — from 2026-07 to
1480
+ * 2026-09-12 a restrictive policy hid every field from its own owner and the screen reported
1481
+ * success. The list used to guess from the whole scope ("no field and no file anywhere" = alarm),
1482
+ * which blanked an organization whose only credential was simply empty (Pinecrest Records'
1483
+ * Bandcamp label login).
1484
+ *
1485
+ * The guess is replaced by the database's own answer: `users.credential_item_holdings(ids)` counts
1486
+ * the live field and file rows of each credential the caller may read (counts only, never a value).
1487
+ * The alarm fires only for a credential that HOLDS something the read did not return.
1488
+ */
1489
+ type HoldingRow = {
1490
+ credential_item_id: string;
1491
+ field_count: number;
1492
+ file_count: number;
1493
+ };
1494
+ type Holdings = {
1495
+ state: "answered";
1496
+ rows: HoldingRow[];
1497
+ }
1498
+ /** The door is not on this database yet — the migration below has not been applied. */
1499
+ | {
1500
+ state: "absent";
1501
+ why: string;
1502
+ } | {
1503
+ state: "unavailable";
1504
+ why: string;
1505
+ };
1506
+ declare const HOLDINGS_DOOR_MIGRATION = "migrations/campaign/errorshonest_s8_a_credential_says_how_much_it_holds.sql";
1507
+ /** The error codes that mean "no such function on this database", not "the read failed". */
1508
+ declare function holdingsDoorIsAbsent(code: string | undefined | null): boolean;
1509
+ /**
1510
+ * The alarm sentence, or null when every credential that read empty is genuinely empty.
1511
+ *
1512
+ * @param total how many credentials the list read
1513
+ * @param emptyIds the ones whose field AND file reads came back empty
1514
+ * @param holdings the database's answer for `emptyIds`
1515
+ */
1516
+ declare function emptyReadAlarm(total: number, emptyIds: readonly string[], holdings: Holdings): string | null;
1517
+
1518
+ export { type ApiVaultPortOptions, CATEGORIES, CONFIRM_RETURN_KEY, type CategoryId, type Confirmed, type CopyOptions, DEFAULT_LOCATION, type DefinitionField, type FieldHandling, type FieldKind, GenerateButton, HIDDEN_ITEM_TAG, HOLDINGS_DOOR_MIGRATION, type HoldingRow, type Holdings, type IdentityAccount, IdentityGate, type IdentityMethod, type ItemDraft, LOCKED_MESSAGE, type NoticeKind, type Notify, type ReturnStore, type RowMenuEntry, type RowMenuEntryKind, type SaveResult, type SupabaseAuthLike, type SupabaseIdentityOptions, type TotpReading, type UriMatchMode, type UrlGuess, type VaultAgentScope, VaultApp, type VaultAppProps, type VaultAttachment, type VaultAuthenticator, type VaultClipboard, type VaultCustomField, type VaultDefinition, type VaultField, type VaultHostCapabilities, type VaultIdentity, type VaultInventory, type VaultItem, type VaultItemCapabilities, type VaultKnobs, type VaultLayout, type VaultLocation, type VaultLock, VaultLockedError, type VaultOrganizationRef, type VaultOwner, type VaultPort, type VaultSelection, type VaultSnapshot, type VaultSort, type VaultUserStateDoor, categoryOf, copyValue, createApiVaultPort, createSupabaseIdentity, createVaultKnobs, emptyReadAlarm, guardPort, holdingsDoorIsAbsent, inferFromUrl, isHiddenItem, itemIdAt, locationFromParams, locationToParams, loginSiteOf, matchesQuery, needsRecentSignIn, parseDefinitions, providerOf, rowMenuEntriesAt, siteDomainOf, sortItems, useConfirmed, vaultInventoryScope, vaultItemFacts, wasCancelled };
package/dist/index.d.ts CHANGED
@@ -1471,4 +1471,48 @@ interface RowMenuEntry {
1471
1471
  /** The entries of the row a right-click landed on (`[data-item]`), else none. */
1472
1472
  declare function rowMenuEntriesAt(target: Element | null | undefined): readonly RowMenuEntry[];
1473
1473
 
1474
- export { type ApiVaultPortOptions, CATEGORIES, CONFIRM_RETURN_KEY, type CategoryId, type Confirmed, type CopyOptions, DEFAULT_LOCATION, type DefinitionField, type FieldHandling, type FieldKind, GenerateButton, HIDDEN_ITEM_TAG, type IdentityAccount, IdentityGate, type IdentityMethod, type ItemDraft, LOCKED_MESSAGE, type NoticeKind, type Notify, type ReturnStore, type RowMenuEntry, type RowMenuEntryKind, type SaveResult, type SupabaseAuthLike, type SupabaseIdentityOptions, type TotpReading, type UriMatchMode, type UrlGuess, type VaultAgentScope, VaultApp, type VaultAppProps, type VaultAttachment, type VaultAuthenticator, type VaultClipboard, type VaultCustomField, type VaultDefinition, type VaultField, type VaultHostCapabilities, type VaultIdentity, type VaultInventory, type VaultItem, type VaultItemCapabilities, type VaultKnobs, type VaultLayout, type VaultLocation, type VaultLock, VaultLockedError, type VaultOrganizationRef, type VaultOwner, type VaultPort, type VaultSelection, type VaultSnapshot, type VaultSort, type VaultUserStateDoor, categoryOf, copyValue, createApiVaultPort, createSupabaseIdentity, createVaultKnobs, guardPort, inferFromUrl, isHiddenItem, itemIdAt, locationFromParams, locationToParams, loginSiteOf, matchesQuery, needsRecentSignIn, parseDefinitions, providerOf, rowMenuEntriesAt, siteDomainOf, sortItems, useConfirmed, vaultInventoryScope, vaultItemFacts, wasCancelled };
1474
+ /**
1475
+ * AN EMPTY CREDENTIAL IS A FACT; AN EMPTY READ OF A FULL ONE IS A FAILURE (DD-160, lane
1476
+ * ERRORS-HONEST 2026-09-24).
1477
+ *
1478
+ * RLS refuses a row by returning nothing, so a list that reads a credential's fields and gets `[]`
1479
+ * cannot tell "there is nothing in it" from "the database filtered the read" — from 2026-07 to
1480
+ * 2026-09-12 a restrictive policy hid every field from its own owner and the screen reported
1481
+ * success. The list used to guess from the whole scope ("no field and no file anywhere" = alarm),
1482
+ * which blanked an organization whose only credential was simply empty (Pinecrest Records'
1483
+ * Bandcamp label login).
1484
+ *
1485
+ * The guess is replaced by the database's own answer: `users.credential_item_holdings(ids)` counts
1486
+ * the live field and file rows of each credential the caller may read (counts only, never a value).
1487
+ * The alarm fires only for a credential that HOLDS something the read did not return.
1488
+ */
1489
+ type HoldingRow = {
1490
+ credential_item_id: string;
1491
+ field_count: number;
1492
+ file_count: number;
1493
+ };
1494
+ type Holdings = {
1495
+ state: "answered";
1496
+ rows: HoldingRow[];
1497
+ }
1498
+ /** The door is not on this database yet — the migration below has not been applied. */
1499
+ | {
1500
+ state: "absent";
1501
+ why: string;
1502
+ } | {
1503
+ state: "unavailable";
1504
+ why: string;
1505
+ };
1506
+ declare const HOLDINGS_DOOR_MIGRATION = "migrations/campaign/errorshonest_s8_a_credential_says_how_much_it_holds.sql";
1507
+ /** The error codes that mean "no such function on this database", not "the read failed". */
1508
+ declare function holdingsDoorIsAbsent(code: string | undefined | null): boolean;
1509
+ /**
1510
+ * The alarm sentence, or null when every credential that read empty is genuinely empty.
1511
+ *
1512
+ * @param total how many credentials the list read
1513
+ * @param emptyIds the ones whose field AND file reads came back empty
1514
+ * @param holdings the database's answer for `emptyIds`
1515
+ */
1516
+ declare function emptyReadAlarm(total: number, emptyIds: readonly string[], holdings: Holdings): string | null;
1517
+
1518
+ export { type ApiVaultPortOptions, CATEGORIES, CONFIRM_RETURN_KEY, type CategoryId, type Confirmed, type CopyOptions, DEFAULT_LOCATION, type DefinitionField, type FieldHandling, type FieldKind, GenerateButton, HIDDEN_ITEM_TAG, HOLDINGS_DOOR_MIGRATION, type HoldingRow, type Holdings, type IdentityAccount, IdentityGate, type IdentityMethod, type ItemDraft, LOCKED_MESSAGE, type NoticeKind, type Notify, type ReturnStore, type RowMenuEntry, type RowMenuEntryKind, type SaveResult, type SupabaseAuthLike, type SupabaseIdentityOptions, type TotpReading, type UriMatchMode, type UrlGuess, type VaultAgentScope, VaultApp, type VaultAppProps, type VaultAttachment, type VaultAuthenticator, type VaultClipboard, type VaultCustomField, type VaultDefinition, type VaultField, type VaultHostCapabilities, type VaultIdentity, type VaultInventory, type VaultItem, type VaultItemCapabilities, type VaultKnobs, type VaultLayout, type VaultLocation, type VaultLock, VaultLockedError, type VaultOrganizationRef, type VaultOwner, type VaultPort, type VaultSelection, type VaultSnapshot, type VaultSort, type VaultUserStateDoor, categoryOf, copyValue, createApiVaultPort, createSupabaseIdentity, createVaultKnobs, emptyReadAlarm, guardPort, holdingsDoorIsAbsent, inferFromUrl, isHiddenItem, itemIdAt, locationFromParams, locationToParams, loginSiteOf, matchesQuery, needsRecentSignIn, parseDefinitions, providerOf, rowMenuEntriesAt, siteDomainOf, sortItems, useConfirmed, vaultInventoryScope, vaultItemFacts, wasCancelled };
package/dist/index.js CHANGED
@@ -9862,12 +9862,42 @@ function vaultInventoryScope(inventory, clicked = null) {
9862
9862
  function itemIdAt(target) {
9863
9863
  return target?.closest("[data-item]")?.getAttribute("data-item") ?? null;
9864
9864
  }
9865
+
9866
+ // src/io/empty-read.ts
9867
+ var HOLDINGS_DOOR_MIGRATION = "migrations/campaign/errorshonest_s8_a_credential_says_how_much_it_holds.sql";
9868
+ function holdingsDoorIsAbsent(code) {
9869
+ return code === "PGRST202" || code === "42883";
9870
+ }
9871
+ function staleAlarm(total) {
9872
+ return `Your vault has ${total} ${total === 1 ? "item" : "items"} but none of their fields or files could be read. Either every one of these items is genuinely still empty, or the database refused the read without reporting an error \u2014 the second is a known failure mode of this screen (DD-160). Nothing has been lost: reload, and if the items are still blank, report it rather than re-entering the credentials.`;
9873
+ }
9874
+ function emptyReadAlarm(total, emptyIds, holdings) {
9875
+ if (emptyIds.length === 0) return null;
9876
+ if (holdings.state === "answered") {
9877
+ const asked = new Set(emptyIds);
9878
+ const unread = holdings.rows.filter(
9879
+ (r) => asked.has(r.credential_item_id) && (r.field_count > 0 || r.file_count > 0)
9880
+ );
9881
+ if (unread.length === 0) return null;
9882
+ const n = unread.length;
9883
+ return `${n === 1 ? "One credential" : `${n} credentials`} in this vault ${n === 1 ? "holds" : "hold"} fields or files this screen could not read \u2014 the database refused the read without reporting an error, a known failure mode of this screen (DD-160). Nothing has been lost: reload, and if ${n === 1 ? "it is" : "they are"} still blank, report it rather than re-entering the credentials.`;
9884
+ }
9885
+ if (emptyIds.length < total) return null;
9886
+ if (holdings.state === "absent") {
9887
+ console.warn(
9888
+ `[vault] users.credential_item_holdings is not on this database (${holdings.why}); the empty-read alarm falls back to the whole-vault rule until ${HOLDINGS_DOOR_MIGRATION} is applied.`
9889
+ );
9890
+ return staleAlarm(total);
9891
+ }
9892
+ return `${staleAlarm(total)} (The check that tells an empty credential from an unreadable one did not answer either: ${holdings.why})`;
9893
+ }
9865
9894
  export {
9866
9895
  CATEGORIES,
9867
9896
  CONFIRM_RETURN_KEY,
9868
9897
  DEFAULT_LOCATION,
9869
9898
  GenerateButton,
9870
9899
  HIDDEN_ITEM_TAG,
9900
+ HOLDINGS_DOOR_MIGRATION,
9871
9901
  IdentityGate,
9872
9902
  LOCKED_MESSAGE,
9873
9903
  VaultApp,
@@ -9877,7 +9907,9 @@ export {
9877
9907
  createApiVaultPort,
9878
9908
  createSupabaseIdentity,
9879
9909
  createVaultKnobs,
9910
+ emptyReadAlarm,
9880
9911
  guardPort,
9912
+ holdingsDoorIsAbsent,
9881
9913
  inferFromUrl,
9882
9914
  isHiddenItem,
9883
9915
  itemIdAt,