@didit-protocol/sdk-node 2.12.0 → 2.13.1

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.cjs CHANGED
@@ -192,6 +192,52 @@ function makeStatusError(status, body, headers, secrets = []) {
192
192
  const ErrorClass = STATUS_ERRORS[status] ?? (status >= 500 ? InternalServerError : APIStatusError);
193
193
  return new ErrorClass(message, status, cleanBody, redactHeaders(headers, secrets));
194
194
  }
195
+ var REDACTED = "[redacted]";
196
+ function redactStructured(value, secrets) {
197
+ const active = secrets.filter((s) => s.length > 0);
198
+ const text = (input) => active.some((secret) => input.includes(secret)) ? REDACTED : input;
199
+ const scrub = (input) => {
200
+ if (typeof input === "string") return text(input);
201
+ if (Array.isArray(input)) return input.map(scrub);
202
+ if (isRecord(input)) {
203
+ const out = /* @__PURE__ */ new Map();
204
+ const taken = new Set(Object.keys(input).filter((key) => text(key) === key));
205
+ let next = 1;
206
+ for (const [key, item] of Object.entries(input)) {
207
+ let name = key;
208
+ if (text(key) !== key) {
209
+ do {
210
+ name = next === 1 ? REDACTED : `${REDACTED}${next}`;
211
+ next++;
212
+ } while (taken.has(name));
213
+ taken.add(name);
214
+ }
215
+ out.set(name, scrub(item));
216
+ }
217
+ return Object.fromEntries(out);
218
+ }
219
+ return input;
220
+ };
221
+ return scrub(value);
222
+ }
223
+ function sanitizeResponse(headers, text, secrets) {
224
+ const clean = new Headers();
225
+ headers.forEach((value, name) => {
226
+ const folded = name.toLowerCase();
227
+ if (!secrets.some((secret) => secret && folded.includes(secret.toLowerCase()))) {
228
+ clean.append(name, redactStructured(value, secrets));
229
+ }
230
+ });
231
+ let body = REDACTED;
232
+ if (text) {
233
+ try {
234
+ body = JSON.stringify(redactStructured(JSON.parse(text), secrets));
235
+ } catch {
236
+ body = REDACTED;
237
+ }
238
+ }
239
+ return { headers: clean, text: body };
240
+ }
195
241
 
196
242
  // src/core/api-promise.ts
197
243
  var APIPromise = class extends Promise {
@@ -282,7 +328,7 @@ function decodeDates(value, plan, named, depth = 0) {
282
328
  }
283
329
 
284
330
  // src/core/version.ts
285
- var VERSION = "2.12.0";
331
+ var VERSION = "2.13.1";
286
332
 
287
333
  // src/core/runtime.ts
288
334
  function processLike() {
@@ -1669,6 +1715,14 @@ var DATE_PLANS = {
1669
1715
  action_required: "TransactionWalletOwnershipAction"
1670
1716
  }
1671
1717
  },
1718
+ TransactionListTravelRule: {
1719
+ p: {
1720
+ data_unmasked: "TravelRuleDataUnmasked",
1721
+ counterparty_vasp: { p: { dd_assessed_at: 1 } },
1722
+ delivery: "TravelRuleDelivery",
1723
+ discovery: { i: "TravelRuleDiscoveryStep" }
1724
+ }
1725
+ },
1672
1726
  TransactionNote: { p: { created_at: 1 } },
1673
1727
  TransactionRuleDetail: { p: { latest_triggered_at: 1, created_at: 1, updated_at: 1 } },
1674
1728
  TransactionSummary: { p: { txn_date: 1, created_at: 1 } },
@@ -1677,7 +1731,8 @@ var DATE_PLANS = {
1677
1731
  data_unmasked: "TravelRuleDataUnmasked",
1678
1732
  counterparty_vasp: { p: { dd_assessed_at: 1 } },
1679
1733
  delivery: "TravelRuleDelivery",
1680
- discovery: { i: "TravelRuleDiscoveryStep" }
1734
+ discovery: { i: "TravelRuleDiscoveryStep" },
1735
+ deliveries: { i: "TravelRuleDeliveryLogEntry" }
1681
1736
  }
1682
1737
  },
1683
1738
  TransactionWalletOwnershipAction: { p: { expires_at: 1 } },
@@ -1685,7 +1740,9 @@ var DATE_PLANS = {
1685
1740
  TransactionsListRelatedResponse: { p: { results: { i: "TransactionSummary" } } },
1686
1741
  TransactionsListResponse: {
1687
1742
  p: {
1688
- results: { i: { p: { txn_date: 1, created_at: 1, travel_rule: "TransactionTravelRule" } } }
1743
+ results: {
1744
+ i: { p: { txn_date: 1, created_at: 1, travel_rule: "TransactionListTravelRule" } }
1745
+ }
1689
1746
  }
1690
1747
  },
1691
1748
  TransactionsNotesListResponse: { p: { results: { i: "TransactionNote" } } },
@@ -1707,6 +1764,8 @@ var DATE_PLANS = {
1707
1764
  TravelRuleCounterpartyScreeningStatus: { p: { screening: "TravelRuleCounterpartyScreening" } },
1708
1765
  TravelRuleDataUnmasked: { p: { at: 1 } },
1709
1766
  TravelRuleDelivery: { p: { next_attempt_at: 1, delivered_at: 1 } },
1767
+ TravelRuleDeliveryLogEntry: { p: { created_at: 1, delivered_at: 1 } },
1768
+ TravelRuleDeliveryLogPage: { p: { results: { i: "TravelRuleDeliveryLogEntry" } } },
1710
1769
  TravelRuleDiscoveryStep: { p: { at: 1 } },
1711
1770
  TravelRuleInboundResponse: { p: { travel_rule: "TravelRuleTransferDetail" } },
1712
1771
  TravelRuleListVaspsResponse: { p: { results: { i: "VaspDirectoryEntry" } } },
@@ -1766,7 +1825,8 @@ var DATE_PLANS = {
1766
1825
  data_unmasked: "TravelRuleDataUnmasked",
1767
1826
  created_at: 1,
1768
1827
  delivery: "TravelRuleDelivery",
1769
- discovery: { i: "TravelRuleDiscoveryStep" }
1828
+ discovery: { i: "TravelRuleDiscoveryStep" },
1829
+ deliveries: { i: "TravelRuleDeliveryLogEntry" }
1770
1830
  }
1771
1831
  },
1772
1832
  TravelRuleTransferRow: { p: { txn_date: 1, deadline_at: 1, created_at: 1 } },
@@ -1952,7 +2012,7 @@ var AccountApplications = class extends APIResource {
1952
2012
  *
1953
2013
  * Create an application inside an organization, in the data location you choose (`data_location`, the European Union by default; it can't be changed afterwards). The response includes `api_key`; persist it now (recoverable via GET). Requires owner/admin JWT.
1954
2014
  *
1955
- * Set initiate_login_uri to your HTTPS sign-in page on the exact website_url hostname, or an empty string to disable admin-sent sign-in links. Changing website_url also revalidates the saved sign-in URI. Invalid values return 400 with an initiate_login_uri field error; hostname and URI policy failures use https_url_on_registered_website_required.
2015
+ * Set initiate_login_uri to your HTTPS sign-in page on the exact website_url hostname, or an empty string to disable admin-sent sign-in links. Changing website_url also revalidates the saved sign-in URI. Invalid values return 400 with an initiate_login_uri field error; hostname and URI policy failures use https_url_on_registered_website_required. An MCP token (a "Log in with Didit" grant, `token_use` `mcp`) also needs the `didit:management` scope, which carries the `applications` resource; a grant limited to `didit:verification` is refused with 403 before anything is created.
1956
2016
  *
1957
2017
  * `POST /organizations/me/{org_id}/applications/`
1958
2018
  *
@@ -1964,7 +2024,7 @@ var AccountApplications = class extends APIResource {
1964
2024
  /**
1965
2025
  * List the organization's applications
1966
2026
  *
1967
- * List the organization's applications, 50 per page by default. Use this to discover `app_id` values when recovering credentials from a new machine, then call `GET /organizations/me/{org_id}/applications/{app_id}/` for the API key. Requires an owner or admin Bearer token.
2027
+ * List the organization's applications, 50 per page by default. Use this to discover `app_id` values when recovering credentials from a new machine, then call `GET /organizations/me/{org_id}/applications/{app_id}/` for the API key. Requires an owner or admin Bearer token. An MCP token (a "Log in with Didit" grant, `token_use` `mcp`) also needs the `didit:management` scope, which carries the `applications` resource; a grant limited to `didit:verification` is refused with 403 before any application is listed.
1968
2028
  *
1969
2029
  * `GET /organizations/me/{org_id}/applications/`
1970
2030
  *
@@ -1976,7 +2036,7 @@ var AccountApplications = class extends APIResource {
1976
2036
  /**
1977
2037
  * Get Application Credentials
1978
2038
  *
1979
- * Read one application's full record including `client_id` and `api_key`. Use this to recover a lost `api_key`.
2039
+ * Read one application's full record including `client_id` and `api_key`. Use this to recover a lost `api_key`. An MCP token (a "Log in with Didit" grant, `token_use` `mcp`) also needs the `didit:management` scope, which carries the `applications` resource; a grant limited to `didit:verification` is refused with 403 before the application is read.
1980
2040
  *
1981
2041
  * `GET /organizations/me/{org_id}/applications/{app_id}/`
1982
2042
  *
@@ -1991,7 +2051,7 @@ var AccountApplications = class extends APIResource {
1991
2051
  *
1992
2052
  * Update application metadata (name, URLs, redirect URIs). `api_key` and `client_id` are never rotated. `products` is read-only: a `products` key in the body is ignored. `data_location` can't be changed after the application is created, except once on the live application created with your organization, while it is unused (see the request body). Requires owner/admin JWT.
1993
2053
  *
1994
- * Set initiate_login_uri to your HTTPS sign-in page on the exact website_url hostname, or an empty string to disable admin-sent sign-in links. Changing website_url also revalidates the saved sign-in URI. Invalid values return 400 with an initiate_login_uri field error; hostname and URI policy failures use https_url_on_registered_website_required.
2054
+ * Set initiate_login_uri to your HTTPS sign-in page on the exact website_url hostname, or an empty string to disable admin-sent sign-in links. Changing website_url also revalidates the saved sign-in URI. Invalid values return 400 with an initiate_login_uri field error; hostname and URI policy failures use https_url_on_registered_website_required. An MCP token (a "Log in with Didit" grant, `token_use` `mcp`) also needs the `didit:management` scope, which carries the `applications` resource; a grant limited to `didit:verification` is refused with 403 before anything is changed.
1995
2055
  *
1996
2056
  * `PATCH /organizations/me/{org_id}/applications/{app_id}/`
1997
2057
  *
@@ -5113,7 +5173,7 @@ var Investigator = class extends APIResource {
5113
5173
  /**
5114
5174
  * Override a recommendation
5115
5175
  *
5116
- * Takes another action with a category and a reason. Also overrides a decision the Investigator took on its own while it still stands. Restricted keys need the `decisions` scope (write); transaction alerts also need `transactions` (write). Escalating a verification or transaction opens a case.
5176
+ * Takes another action with a category and a reason. Also overrides a decision the Investigator took on its own while it still stands. Restricted keys need the `decisions` scope (write); transaction alerts also need `transactions` (write). Escalating a verification or transaction opens a case. Automated transaction decisions can be overridden only while the original decision still stands. The original decision remains unchanged, the override is recorded separately, and an immediate policy question is raised for its recorded situations with the original policy action. The override does not charge for another automated decision.
5117
5177
  *
5118
5178
  * `POST /v3/investigator/runs/{run_id}/override/`
5119
5179
  *
@@ -8050,6 +8110,12 @@ var TRANSACTIONS_TRAVEL_RULE_CREATE_MESSAGE = {
8050
8110
  body: "json",
8051
8111
  dates: "TravelRuleMessage"
8052
8112
  };
8113
+ var TRANSACTIONS_TRAVEL_RULE_LIST_DELIVERIES = {
8114
+ method: "GET",
8115
+ path: "/v3/transactions/{transaction_id}/travel-rule/deliveries/",
8116
+ query: ["limit", "offset"],
8117
+ dates: "TravelRuleDeliveryLogPage"
8118
+ };
8053
8119
  var TRANSACTIONS_TRAVEL_RULE_LIST_MESSAGES = {
8054
8120
  method: "GET",
8055
8121
  path: "/v3/transactions/{transaction_id}/travel-rule/messages/",
@@ -8099,7 +8165,9 @@ var TRANSACTIONS_LIST = {
8099
8165
  query: ["limit", "offset", "travel_rule_status", "assignee"],
8100
8166
  dates: {
8101
8167
  p: {
8102
- results: { i: { p: { txn_date: 1, created_at: 1, travel_rule: "TransactionTravelRule" } } }
8168
+ results: {
8169
+ i: { p: { txn_date: 1, created_at: 1, travel_rule: "TransactionListTravelRule" } }
8170
+ }
8103
8171
  }
8104
8172
  }
8105
8173
  };
@@ -8293,6 +8361,23 @@ var TransactionsTravelRule = class extends APIResource {
8293
8361
  options
8294
8362
  );
8295
8363
  }
8364
+ /**
8365
+ * List Travel Rule delivery history
8366
+ *
8367
+ * Read the complete delivery history for a transaction, oldest first. Requires transaction read permission. Unlike the newest 100 entries embedded in detail, this endpoint paginates the full history. See [delivery history](/management-api/travel-rule/list-deliveries).
8368
+ *
8369
+ * `GET /v3/transactions/{transaction_id}/travel-rule/deliveries/`
8370
+ *
8371
+ * @param transactionId Didit-stable transaction UUID that owns the transfer.
8372
+ */
8373
+ listDeliveries(transactionId, params = {}, options) {
8374
+ return this._client.requestPage(
8375
+ TRANSACTIONS_TRAVEL_RULE_LIST_DELIVERIES,
8376
+ [transactionId],
8377
+ params,
8378
+ options
8379
+ );
8380
+ }
8296
8381
  /**
8297
8382
  * List Travel Rule messages
8298
8383
  *
@@ -11136,11 +11221,15 @@ async function send(transport, request) {
11136
11221
  log(null, null, "timeout");
11137
11222
  return new APITimeoutError(
11138
11223
  `The issuer did not answer ${method} ${path} within ${transport.timeout} ms.`,
11139
- { cause }
11224
+ // A request that carries secrets keeps no cause: a transport may quote the serialized body in it.
11225
+ request.structuredRedaction ? void 0 : { cause }
11140
11226
  );
11141
11227
  }
11142
11228
  log(null, null, "connection_error");
11143
- return new APIConnectionError(`Could not reach the issuer for ${method} ${path}.`, { cause });
11229
+ return new APIConnectionError(
11230
+ `Could not reach the issuer for ${method} ${path}.`,
11231
+ request.structuredRedaction ? void 0 : { cause }
11232
+ );
11144
11233
  };
11145
11234
  let status;
11146
11235
  let responseHeaders;
@@ -11168,19 +11257,28 @@ async function send(transport, request) {
11168
11257
  } finally {
11169
11258
  clearTimeout(timer);
11170
11259
  }
11171
- log(status, responseHeaders);
11260
+ const secrets = request.secrets ?? [];
11261
+ const sanitized = request.structuredRedaction ? sanitizeResponse(responseHeaders, text, secrets) : null;
11262
+ const errorHeaders = sanitized?.headers ?? responseHeaders;
11263
+ log(status, errorHeaders);
11172
11264
  if (status < 200 || status > 299) {
11173
- throw makeStatusError(status, bodyOf(text), responseHeaders, request.secrets ?? []);
11265
+ throw makeStatusError(
11266
+ status,
11267
+ bodyOf(sanitized?.text ?? text),
11268
+ errorHeaders,
11269
+ sanitized ? [] : secrets
11270
+ );
11174
11271
  }
11175
- if (status === 204 || !text) return { status, headers: responseHeaders, data: null };
11272
+ if (status === 204 || !text)
11273
+ return { status, headers: responseHeaders, errorHeaders, data: null };
11176
11274
  try {
11177
- return { status, headers: responseHeaders, data: JSON.parse(text) };
11275
+ return { status, headers: responseHeaders, errorHeaders, data: JSON.parse(text) };
11178
11276
  } catch {
11179
- const type = responseHeaders.get("content-type") ?? "no content type";
11277
+ const type = errorHeaders.get("content-type") ?? "no content type";
11180
11278
  throw new APIResponseValidationError(
11181
11279
  `Expected a JSON response from ${method} ${path}, got ${type}.`,
11182
11280
  status,
11183
- responseHeaders
11281
+ errorHeaders
11184
11282
  );
11185
11283
  }
11186
11284
  }
@@ -11285,10 +11383,16 @@ function textList(value, name) {
11285
11383
  }
11286
11384
  return [...value];
11287
11385
  }
11386
+ var MIN_SECRET_LENGTH = 16;
11288
11387
  function assertionSecrets(value) {
11289
- if (typeof value === "string") return value.length > 0 ? [value] : [];
11388
+ if (typeof value === "string") return value.length >= MIN_SECRET_LENGTH ? [value] : [];
11290
11389
  if (Array.isArray(value)) return value.flatMap(assertionSecrets);
11291
- if (isRecord4(value)) return Object.values(value).flatMap(assertionSecrets);
11390
+ if (isRecord4(value)) {
11391
+ return Object.entries(value).flatMap(([key, item]) => [
11392
+ ...assertionSecrets(key),
11393
+ ...assertionSecrets(item)
11394
+ ]);
11395
+ }
11292
11396
  return [];
11293
11397
  }
11294
11398
  function optionalText(value, name) {
@@ -11568,7 +11672,6 @@ var Authentication = class _Authentication {
11568
11672
  if (assertion !== void 0 && assertion !== null) {
11569
11673
  if (!isRecord4(assertion)) throw new TypeError("assertion must be an object.");
11570
11674
  body.assertion = assertion;
11571
- secrets.push(...assertionSecrets(assertion));
11572
11675
  }
11573
11676
  const scopes = given.scopes;
11574
11677
  if (scopes !== void 0 && scopes !== null) body.scopes = textList(scopes, "scopes");
@@ -11583,7 +11686,19 @@ var Authentication = class _Authentication {
11583
11686
  }
11584
11687
  body.lifetime = lifetime;
11585
11688
  }
11586
- const call = { ...this.#bearerCall("POST", AGENT_CONSENT_PATH, token), json: body, secrets };
11689
+ let sent;
11690
+ try {
11691
+ sent = JSON.parse(JSON.stringify(body));
11692
+ } catch {
11693
+ throw new TypeError("Could not encode the agent consent request.");
11694
+ }
11695
+ secrets.push(...assertionSecrets(sent.assertion));
11696
+ const call = {
11697
+ ...this.#bearerCall("POST", AGENT_CONSENT_PATH, token),
11698
+ json: sent,
11699
+ secrets,
11700
+ structuredRedaction: true
11701
+ };
11587
11702
  return await this.#object(call);
11588
11703
  }
11589
11704
  /**
@@ -11599,7 +11714,8 @@ var Authentication = class _Authentication {
11599
11714
  const call = {
11600
11715
  ...this.#bearerCall("POST", AGENT_CONSENT_PASSKEY_PATH, token),
11601
11716
  json: { challenge },
11602
- secrets: [token, challenge]
11717
+ secrets: [token, challenge],
11718
+ structuredRedaction: true
11603
11719
  };
11604
11720
  return await this.#object(call);
11605
11721
  }
@@ -11619,7 +11735,7 @@ var Authentication = class _Authentication {
11619
11735
  throw new APIResponseValidationError(
11620
11736
  `Expected a JSON object from ${call.method} ${pathOf(call.url)}.`,
11621
11737
  response.status,
11622
- response.headers
11738
+ response.errorHeaders
11623
11739
  );
11624
11740
  }
11625
11741
  return response.data;