@didit-protocol/sdk-node 2.13.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.13.0";
331
+ var VERSION = "2.13.1";
286
332
 
287
333
  // src/core/runtime.ts
288
334
  function processLike() {
@@ -11175,11 +11221,15 @@ async function send(transport, request) {
11175
11221
  log(null, null, "timeout");
11176
11222
  return new APITimeoutError(
11177
11223
  `The issuer did not answer ${method} ${path} within ${transport.timeout} ms.`,
11178
- { 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 }
11179
11226
  );
11180
11227
  }
11181
11228
  log(null, null, "connection_error");
11182
- 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
+ );
11183
11233
  };
11184
11234
  let status;
11185
11235
  let responseHeaders;
@@ -11207,19 +11257,28 @@ async function send(transport, request) {
11207
11257
  } finally {
11208
11258
  clearTimeout(timer);
11209
11259
  }
11210
- 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);
11211
11264
  if (status < 200 || status > 299) {
11212
- throw makeStatusError(status, bodyOf(text), responseHeaders, request.secrets ?? []);
11265
+ throw makeStatusError(
11266
+ status,
11267
+ bodyOf(sanitized?.text ?? text),
11268
+ errorHeaders,
11269
+ sanitized ? [] : secrets
11270
+ );
11213
11271
  }
11214
- if (status === 204 || !text) return { status, headers: responseHeaders, data: null };
11272
+ if (status === 204 || !text)
11273
+ return { status, headers: responseHeaders, errorHeaders, data: null };
11215
11274
  try {
11216
- return { status, headers: responseHeaders, data: JSON.parse(text) };
11275
+ return { status, headers: responseHeaders, errorHeaders, data: JSON.parse(text) };
11217
11276
  } catch {
11218
- const type = responseHeaders.get("content-type") ?? "no content type";
11277
+ const type = errorHeaders.get("content-type") ?? "no content type";
11219
11278
  throw new APIResponseValidationError(
11220
11279
  `Expected a JSON response from ${method} ${path}, got ${type}.`,
11221
11280
  status,
11222
- responseHeaders
11281
+ errorHeaders
11223
11282
  );
11224
11283
  }
11225
11284
  }
@@ -11324,10 +11383,16 @@ function textList(value, name) {
11324
11383
  }
11325
11384
  return [...value];
11326
11385
  }
11386
+ var MIN_SECRET_LENGTH = 16;
11327
11387
  function assertionSecrets(value) {
11328
- if (typeof value === "string") return value.length > 0 ? [value] : [];
11388
+ if (typeof value === "string") return value.length >= MIN_SECRET_LENGTH ? [value] : [];
11329
11389
  if (Array.isArray(value)) return value.flatMap(assertionSecrets);
11330
- 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
+ }
11331
11396
  return [];
11332
11397
  }
11333
11398
  function optionalText(value, name) {
@@ -11607,7 +11672,6 @@ var Authentication = class _Authentication {
11607
11672
  if (assertion !== void 0 && assertion !== null) {
11608
11673
  if (!isRecord4(assertion)) throw new TypeError("assertion must be an object.");
11609
11674
  body.assertion = assertion;
11610
- secrets.push(...assertionSecrets(assertion));
11611
11675
  }
11612
11676
  const scopes = given.scopes;
11613
11677
  if (scopes !== void 0 && scopes !== null) body.scopes = textList(scopes, "scopes");
@@ -11622,7 +11686,19 @@ var Authentication = class _Authentication {
11622
11686
  }
11623
11687
  body.lifetime = lifetime;
11624
11688
  }
11625
- 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
+ };
11626
11702
  return await this.#object(call);
11627
11703
  }
11628
11704
  /**
@@ -11638,7 +11714,8 @@ var Authentication = class _Authentication {
11638
11714
  const call = {
11639
11715
  ...this.#bearerCall("POST", AGENT_CONSENT_PASSKEY_PATH, token),
11640
11716
  json: { challenge },
11641
- secrets: [token, challenge]
11717
+ secrets: [token, challenge],
11718
+ structuredRedaction: true
11642
11719
  };
11643
11720
  return await this.#object(call);
11644
11721
  }
@@ -11658,7 +11735,7 @@ var Authentication = class _Authentication {
11658
11735
  throw new APIResponseValidationError(
11659
11736
  `Expected a JSON object from ${call.method} ${pathOf(call.url)}.`,
11660
11737
  response.status,
11661
- response.headers
11738
+ response.errorHeaders
11662
11739
  );
11663
11740
  }
11664
11741
  return response.data;