@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.js CHANGED
@@ -188,6 +188,52 @@ function makeStatusError(status, body, headers, secrets = []) {
188
188
  const ErrorClass = STATUS_ERRORS[status] ?? (status >= 500 ? InternalServerError : APIStatusError);
189
189
  return new ErrorClass(message, status, cleanBody, redactHeaders(headers, secrets));
190
190
  }
191
+ var REDACTED = "[redacted]";
192
+ function redactStructured(value, secrets) {
193
+ const active = secrets.filter((s) => s.length > 0);
194
+ const text = (input) => active.some((secret) => input.includes(secret)) ? REDACTED : input;
195
+ const scrub = (input) => {
196
+ if (typeof input === "string") return text(input);
197
+ if (Array.isArray(input)) return input.map(scrub);
198
+ if (isRecord(input)) {
199
+ const out = /* @__PURE__ */ new Map();
200
+ const taken = new Set(Object.keys(input).filter((key) => text(key) === key));
201
+ let next = 1;
202
+ for (const [key, item] of Object.entries(input)) {
203
+ let name = key;
204
+ if (text(key) !== key) {
205
+ do {
206
+ name = next === 1 ? REDACTED : `${REDACTED}${next}`;
207
+ next++;
208
+ } while (taken.has(name));
209
+ taken.add(name);
210
+ }
211
+ out.set(name, scrub(item));
212
+ }
213
+ return Object.fromEntries(out);
214
+ }
215
+ return input;
216
+ };
217
+ return scrub(value);
218
+ }
219
+ function sanitizeResponse(headers, text, secrets) {
220
+ const clean = new Headers();
221
+ headers.forEach((value, name) => {
222
+ const folded = name.toLowerCase();
223
+ if (!secrets.some((secret) => secret && folded.includes(secret.toLowerCase()))) {
224
+ clean.append(name, redactStructured(value, secrets));
225
+ }
226
+ });
227
+ let body = REDACTED;
228
+ if (text) {
229
+ try {
230
+ body = JSON.stringify(redactStructured(JSON.parse(text), secrets));
231
+ } catch {
232
+ body = REDACTED;
233
+ }
234
+ }
235
+ return { headers: clean, text: body };
236
+ }
191
237
 
192
238
  // src/core/api-promise.ts
193
239
  var APIPromise = class extends Promise {
@@ -278,7 +324,7 @@ function decodeDates(value, plan, named, depth = 0) {
278
324
  }
279
325
 
280
326
  // src/core/version.ts
281
- var VERSION = "2.12.0";
327
+ var VERSION = "2.13.1";
282
328
 
283
329
  // src/core/runtime.ts
284
330
  function processLike() {
@@ -1665,6 +1711,14 @@ var DATE_PLANS = {
1665
1711
  action_required: "TransactionWalletOwnershipAction"
1666
1712
  }
1667
1713
  },
1714
+ TransactionListTravelRule: {
1715
+ p: {
1716
+ data_unmasked: "TravelRuleDataUnmasked",
1717
+ counterparty_vasp: { p: { dd_assessed_at: 1 } },
1718
+ delivery: "TravelRuleDelivery",
1719
+ discovery: { i: "TravelRuleDiscoveryStep" }
1720
+ }
1721
+ },
1668
1722
  TransactionNote: { p: { created_at: 1 } },
1669
1723
  TransactionRuleDetail: { p: { latest_triggered_at: 1, created_at: 1, updated_at: 1 } },
1670
1724
  TransactionSummary: { p: { txn_date: 1, created_at: 1 } },
@@ -1673,7 +1727,8 @@ var DATE_PLANS = {
1673
1727
  data_unmasked: "TravelRuleDataUnmasked",
1674
1728
  counterparty_vasp: { p: { dd_assessed_at: 1 } },
1675
1729
  delivery: "TravelRuleDelivery",
1676
- discovery: { i: "TravelRuleDiscoveryStep" }
1730
+ discovery: { i: "TravelRuleDiscoveryStep" },
1731
+ deliveries: { i: "TravelRuleDeliveryLogEntry" }
1677
1732
  }
1678
1733
  },
1679
1734
  TransactionWalletOwnershipAction: { p: { expires_at: 1 } },
@@ -1681,7 +1736,9 @@ var DATE_PLANS = {
1681
1736
  TransactionsListRelatedResponse: { p: { results: { i: "TransactionSummary" } } },
1682
1737
  TransactionsListResponse: {
1683
1738
  p: {
1684
- results: { i: { p: { txn_date: 1, created_at: 1, travel_rule: "TransactionTravelRule" } } }
1739
+ results: {
1740
+ i: { p: { txn_date: 1, created_at: 1, travel_rule: "TransactionListTravelRule" } }
1741
+ }
1685
1742
  }
1686
1743
  },
1687
1744
  TransactionsNotesListResponse: { p: { results: { i: "TransactionNote" } } },
@@ -1703,6 +1760,8 @@ var DATE_PLANS = {
1703
1760
  TravelRuleCounterpartyScreeningStatus: { p: { screening: "TravelRuleCounterpartyScreening" } },
1704
1761
  TravelRuleDataUnmasked: { p: { at: 1 } },
1705
1762
  TravelRuleDelivery: { p: { next_attempt_at: 1, delivered_at: 1 } },
1763
+ TravelRuleDeliveryLogEntry: { p: { created_at: 1, delivered_at: 1 } },
1764
+ TravelRuleDeliveryLogPage: { p: { results: { i: "TravelRuleDeliveryLogEntry" } } },
1706
1765
  TravelRuleDiscoveryStep: { p: { at: 1 } },
1707
1766
  TravelRuleInboundResponse: { p: { travel_rule: "TravelRuleTransferDetail" } },
1708
1767
  TravelRuleListVaspsResponse: { p: { results: { i: "VaspDirectoryEntry" } } },
@@ -1762,7 +1821,8 @@ var DATE_PLANS = {
1762
1821
  data_unmasked: "TravelRuleDataUnmasked",
1763
1822
  created_at: 1,
1764
1823
  delivery: "TravelRuleDelivery",
1765
- discovery: { i: "TravelRuleDiscoveryStep" }
1824
+ discovery: { i: "TravelRuleDiscoveryStep" },
1825
+ deliveries: { i: "TravelRuleDeliveryLogEntry" }
1766
1826
  }
1767
1827
  },
1768
1828
  TravelRuleTransferRow: { p: { txn_date: 1, deadline_at: 1, created_at: 1 } },
@@ -1948,7 +2008,7 @@ var AccountApplications = class extends APIResource {
1948
2008
  *
1949
2009
  * 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.
1950
2010
  *
1951
- * 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.
2011
+ * 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.
1952
2012
  *
1953
2013
  * `POST /organizations/me/{org_id}/applications/`
1954
2014
  *
@@ -1960,7 +2020,7 @@ var AccountApplications = class extends APIResource {
1960
2020
  /**
1961
2021
  * List the organization's applications
1962
2022
  *
1963
- * 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.
2023
+ * 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.
1964
2024
  *
1965
2025
  * `GET /organizations/me/{org_id}/applications/`
1966
2026
  *
@@ -1972,7 +2032,7 @@ var AccountApplications = class extends APIResource {
1972
2032
  /**
1973
2033
  * Get Application Credentials
1974
2034
  *
1975
- * Read one application's full record including `client_id` and `api_key`. Use this to recover a lost `api_key`.
2035
+ * 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.
1976
2036
  *
1977
2037
  * `GET /organizations/me/{org_id}/applications/{app_id}/`
1978
2038
  *
@@ -1987,7 +2047,7 @@ var AccountApplications = class extends APIResource {
1987
2047
  *
1988
2048
  * 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.
1989
2049
  *
1990
- * 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.
2050
+ * 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.
1991
2051
  *
1992
2052
  * `PATCH /organizations/me/{org_id}/applications/{app_id}/`
1993
2053
  *
@@ -5109,7 +5169,7 @@ var Investigator = class extends APIResource {
5109
5169
  /**
5110
5170
  * Override a recommendation
5111
5171
  *
5112
- * 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.
5172
+ * 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.
5113
5173
  *
5114
5174
  * `POST /v3/investigator/runs/{run_id}/override/`
5115
5175
  *
@@ -8046,6 +8106,12 @@ var TRANSACTIONS_TRAVEL_RULE_CREATE_MESSAGE = {
8046
8106
  body: "json",
8047
8107
  dates: "TravelRuleMessage"
8048
8108
  };
8109
+ var TRANSACTIONS_TRAVEL_RULE_LIST_DELIVERIES = {
8110
+ method: "GET",
8111
+ path: "/v3/transactions/{transaction_id}/travel-rule/deliveries/",
8112
+ query: ["limit", "offset"],
8113
+ dates: "TravelRuleDeliveryLogPage"
8114
+ };
8049
8115
  var TRANSACTIONS_TRAVEL_RULE_LIST_MESSAGES = {
8050
8116
  method: "GET",
8051
8117
  path: "/v3/transactions/{transaction_id}/travel-rule/messages/",
@@ -8095,7 +8161,9 @@ var TRANSACTIONS_LIST = {
8095
8161
  query: ["limit", "offset", "travel_rule_status", "assignee"],
8096
8162
  dates: {
8097
8163
  p: {
8098
- results: { i: { p: { txn_date: 1, created_at: 1, travel_rule: "TransactionTravelRule" } } }
8164
+ results: {
8165
+ i: { p: { txn_date: 1, created_at: 1, travel_rule: "TransactionListTravelRule" } }
8166
+ }
8099
8167
  }
8100
8168
  }
8101
8169
  };
@@ -8289,6 +8357,23 @@ var TransactionsTravelRule = class extends APIResource {
8289
8357
  options
8290
8358
  );
8291
8359
  }
8360
+ /**
8361
+ * List Travel Rule delivery history
8362
+ *
8363
+ * 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).
8364
+ *
8365
+ * `GET /v3/transactions/{transaction_id}/travel-rule/deliveries/`
8366
+ *
8367
+ * @param transactionId Didit-stable transaction UUID that owns the transfer.
8368
+ */
8369
+ listDeliveries(transactionId, params = {}, options) {
8370
+ return this._client.requestPage(
8371
+ TRANSACTIONS_TRAVEL_RULE_LIST_DELIVERIES,
8372
+ [transactionId],
8373
+ params,
8374
+ options
8375
+ );
8376
+ }
8292
8377
  /**
8293
8378
  * List Travel Rule messages
8294
8379
  *
@@ -11132,11 +11217,15 @@ async function send(transport, request) {
11132
11217
  log(null, null, "timeout");
11133
11218
  return new APITimeoutError(
11134
11219
  `The issuer did not answer ${method} ${path} within ${transport.timeout} ms.`,
11135
- { cause }
11220
+ // A request that carries secrets keeps no cause: a transport may quote the serialized body in it.
11221
+ request.structuredRedaction ? void 0 : { cause }
11136
11222
  );
11137
11223
  }
11138
11224
  log(null, null, "connection_error");
11139
- return new APIConnectionError(`Could not reach the issuer for ${method} ${path}.`, { cause });
11225
+ return new APIConnectionError(
11226
+ `Could not reach the issuer for ${method} ${path}.`,
11227
+ request.structuredRedaction ? void 0 : { cause }
11228
+ );
11140
11229
  };
11141
11230
  let status;
11142
11231
  let responseHeaders;
@@ -11164,19 +11253,28 @@ async function send(transport, request) {
11164
11253
  } finally {
11165
11254
  clearTimeout(timer);
11166
11255
  }
11167
- log(status, responseHeaders);
11256
+ const secrets = request.secrets ?? [];
11257
+ const sanitized = request.structuredRedaction ? sanitizeResponse(responseHeaders, text, secrets) : null;
11258
+ const errorHeaders = sanitized?.headers ?? responseHeaders;
11259
+ log(status, errorHeaders);
11168
11260
  if (status < 200 || status > 299) {
11169
- throw makeStatusError(status, bodyOf(text), responseHeaders, request.secrets ?? []);
11261
+ throw makeStatusError(
11262
+ status,
11263
+ bodyOf(sanitized?.text ?? text),
11264
+ errorHeaders,
11265
+ sanitized ? [] : secrets
11266
+ );
11170
11267
  }
11171
- if (status === 204 || !text) return { status, headers: responseHeaders, data: null };
11268
+ if (status === 204 || !text)
11269
+ return { status, headers: responseHeaders, errorHeaders, data: null };
11172
11270
  try {
11173
- return { status, headers: responseHeaders, data: JSON.parse(text) };
11271
+ return { status, headers: responseHeaders, errorHeaders, data: JSON.parse(text) };
11174
11272
  } catch {
11175
- const type = responseHeaders.get("content-type") ?? "no content type";
11273
+ const type = errorHeaders.get("content-type") ?? "no content type";
11176
11274
  throw new APIResponseValidationError(
11177
11275
  `Expected a JSON response from ${method} ${path}, got ${type}.`,
11178
11276
  status,
11179
- responseHeaders
11277
+ errorHeaders
11180
11278
  );
11181
11279
  }
11182
11280
  }
@@ -11281,10 +11379,16 @@ function textList(value, name) {
11281
11379
  }
11282
11380
  return [...value];
11283
11381
  }
11382
+ var MIN_SECRET_LENGTH = 16;
11284
11383
  function assertionSecrets(value) {
11285
- if (typeof value === "string") return value.length > 0 ? [value] : [];
11384
+ if (typeof value === "string") return value.length >= MIN_SECRET_LENGTH ? [value] : [];
11286
11385
  if (Array.isArray(value)) return value.flatMap(assertionSecrets);
11287
- if (isRecord4(value)) return Object.values(value).flatMap(assertionSecrets);
11386
+ if (isRecord4(value)) {
11387
+ return Object.entries(value).flatMap(([key, item]) => [
11388
+ ...assertionSecrets(key),
11389
+ ...assertionSecrets(item)
11390
+ ]);
11391
+ }
11288
11392
  return [];
11289
11393
  }
11290
11394
  function optionalText(value, name) {
@@ -11564,7 +11668,6 @@ var Authentication = class _Authentication {
11564
11668
  if (assertion !== void 0 && assertion !== null) {
11565
11669
  if (!isRecord4(assertion)) throw new TypeError("assertion must be an object.");
11566
11670
  body.assertion = assertion;
11567
- secrets.push(...assertionSecrets(assertion));
11568
11671
  }
11569
11672
  const scopes = given.scopes;
11570
11673
  if (scopes !== void 0 && scopes !== null) body.scopes = textList(scopes, "scopes");
@@ -11579,7 +11682,19 @@ var Authentication = class _Authentication {
11579
11682
  }
11580
11683
  body.lifetime = lifetime;
11581
11684
  }
11582
- const call = { ...this.#bearerCall("POST", AGENT_CONSENT_PATH, token), json: body, secrets };
11685
+ let sent;
11686
+ try {
11687
+ sent = JSON.parse(JSON.stringify(body));
11688
+ } catch {
11689
+ throw new TypeError("Could not encode the agent consent request.");
11690
+ }
11691
+ secrets.push(...assertionSecrets(sent.assertion));
11692
+ const call = {
11693
+ ...this.#bearerCall("POST", AGENT_CONSENT_PATH, token),
11694
+ json: sent,
11695
+ secrets,
11696
+ structuredRedaction: true
11697
+ };
11583
11698
  return await this.#object(call);
11584
11699
  }
11585
11700
  /**
@@ -11595,7 +11710,8 @@ var Authentication = class _Authentication {
11595
11710
  const call = {
11596
11711
  ...this.#bearerCall("POST", AGENT_CONSENT_PASSKEY_PATH, token),
11597
11712
  json: { challenge },
11598
- secrets: [token, challenge]
11713
+ secrets: [token, challenge],
11714
+ structuredRedaction: true
11599
11715
  };
11600
11716
  return await this.#object(call);
11601
11717
  }
@@ -11615,7 +11731,7 @@ var Authentication = class _Authentication {
11615
11731
  throw new APIResponseValidationError(
11616
11732
  `Expected a JSON object from ${call.method} ${pathOf(call.url)}.`,
11617
11733
  response.status,
11618
- response.headers
11734
+ response.errorHeaders
11619
11735
  );
11620
11736
  }
11621
11737
  return response.data;